Description

你准备给弟弟 Ike 买一件礼物,但是,Ike 挑选礼物的方式很特别:他只喜欢那些能被他排成有序形状的东西。

你准备给 Ike 买一个风铃。风铃是一种多层的装饰品,一般挂在天花板上。

每个风铃都包含一些由竖直线连起来的水平杆。每根杆的两头都有线连接,下面或者挂着另一根水平杆,或者挂着一个玩具。下面是一个风铃的例子:

为了满足弟弟,你需要选一个满足下面两个条件的风铃:

(1) 所有的玩具都在同一层(也就是说,每个玩具到天花板之间的杆的个数是一样的)或至多相差一层。

(2) 对于两个相差一层的玩具,左边的玩具比右边的玩具要更靠下一点。

风铃可以按照下面的规则重新排列:任选一根杆,将杆两头的线“交换”。也就是解开一根杆左右两头的线,然后将它们绑到杆的另一头。这个操作不会改变更下面的杆上线的排列顺序。正在训练信息学奥林匹克的你,决定设计一个算法,判断能否通过重新排列,将一个给定的风铃变为 Ike 喜欢的样子。

考虑上面的例子,上图中的风铃满足条件(1),却不满足条件(2)——最左边的那个玩具比它右边的要高。

但是,我们可以通过下面的步骤把这个风铃变成一个 Ike 喜欢的:

第一步,将杆 1 的左右两边交换,这使得杆 2 和杆 3 的位置互换,交换的结果如下图所示:

第二步,也是最后一步,将杆 2 的左右两边交换,这使得杆 4 到了左边,原来在左边的玩具到了右边,交换的结果发下图所示:

现在的这个风铃就满足 Ike 的条件了。

你的任务是:给定一个风铃的描述,求出最少需要多少次交换才能使这风铃满足 Ike 的条件(如果可能)

Input

输入的第一行包含一个整数 n(1≤n≤100 000),表示风铃中有多少根杆。

接下来的 n 行描述杆的连接信息。这部分的第 i 行包含两个由空格分隔的整数 li和 ri,描述杆 i 的左右两边悬挂的东西。如果挂的是一个玩具,则对应的值为-1,否则为挂在下面的杆的编号

Output

输出仅包含一个整数。表示最少需要多少次交换能使风铃满足 Ike 的条件。如果不可能满足,输出-1。

Sample Input

6

2 3

-1 4

5 6

-1 -1

-1 -1

-1 -1

Sample Output

2


想法

才不会说我是看这个题目好玩才去做的呢

这个题目让我想起了林清玄的散文《风铃》:

有了风铃,风虽然吹过了,还留下美妙的声音

有了心的风铃,生命即使走过了,也会留下动人的痕迹

每一次起风的时候,每一步岁月的脚步,都会那样真实地存在。

等等,跑题了!

这个题就是树形dp嘛,注意判断几种不行的情况:

1.风铃相差层数>1

2.在满足风铃相差层数为1的情况下,把在上面一层的风铃统称为F,把下面一层的风铃统称为G

在某一节点,其两个子节点中都既有F又有G

然后注意各种细节就好了(自古树形dp细节多qwq)


代码

#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; const int N = 100005; int ch[N][2],pa[N],dep[N];
int n,rt; int m,d[N],t;
void get_dep(int u){
for(int i=0;i<2;i++){
if(ch[u][i]!=-1){
dep[ch[u][i]]=dep[u]+1;
get_dep(ch[u][i]);
}
else d[m++]=dep[u]+1,t=max(t,d[m-1]);
}
}
int sz[N],num[N]; //num表示该节点子树中F与G的总和,sz表示该节点子树中F个数
void dfs0(int u){
for(int i=0;i<2;i++){
if(ch[u][i]!=-1){
dfs0(ch[u][i]);
num[u]+=num[ch[u][i]]; sz[u]+=sz[ch[u][i]];
}
else {
num[u]++;
if(dep[u]+1==t-1) sz[u]++;
}
}
} int flag;
int dfs(int u){
if(sz[u]==0 || sz[u]==num[u]) return 0;
if(ch[u][0]!=-1 && ch[u][1]!=-1){
if(sz[ch[u][0]]==0) return dfs(ch[u][1]);
if(sz[ch[u][1]]==0) return dfs(ch[u][0])+1;
if(sz[ch[u][0]]==num[ch[u][0]]) return dfs(ch[u][1])+1;
if(sz[ch[u][1]]==num[ch[u][1]]) return dfs(ch[u][0]);
flag=0; return 0;
}
if(ch[u][0]==-1 && ch[u][1]!=-1){
if(sz[ch[u][1]]==0) return 1;
return dfs(ch[u][1])+1;
}
if(ch[u][0]!=-1 && ch[u][1]==-1){
if(sz[ch[u][0]]==0) return 0;
return dfs(ch[u][0]);
}
return 0;
} int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&ch[i][0],&ch[i][1]);
if(ch[i][0]!=-1) pa[ch[i][0]]=i;
if(ch[i][1]!=-1) pa[ch[i][1]]=i;
} for(int i=1;i<=n;i++) if(!pa[i]) { rt=i; break; }
dep[rt]=1; get_dep(rt); flag=1;
for(int i=0;i<m;i++) if(d[i]<t-1) flag=0;
if(flag==0) { printf("-1"); return 0; } dfs0(rt);
if(sz[rt]==0) { printf("0"); return 0; } int ans=dfs(rt);
if(flag==0) printf("-1");
else printf("%d",ans); return 0;
}

[洛谷P3621] [APIO2007] 风铃的更多相关文章

  1. 洛谷 P3621 [APIO2007]风铃【贪心】

    没有算法,但是要注意细节. 首先无解的情况,显然的是最小深度的叶子节点和最大深度的叶子节点的深度差大于1:还有一种比较难想,就是如果一个点的左右子树都有最大和最小深度的叶子节点,这样交换左右子树也不行 ...

  2. 洛谷P3621风铃

    传送门啦 分析: 这个题看起来像是个树形dp,嗯,就是看起来像. 所以我们就按树形dp的思路去分析就好了,这个题是一个树形dp的变形题. 和以前建树是一样的,我们用邻接表来进行储存.利用邻接表的特性, ...

  3. 洛谷 P3622 [APIO2007]动物园【状压dp】

    看成网络流建图想了好久... 实际上5个是可以状压的 设f[i][k]为到第i个围栏状态为k的方案数,因为考虑到重复,设g[i][k]记录i开始,状态为k的孩子有几个 状态转移很好想:f[j][k]= ...

  4. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

  5. 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.

    没有上司的舞会  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...

  6. 洛谷P1108 低价购买[DP | LIS方案数]

    题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...

  7. 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP

    题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...

  8. 洛谷P1710 地铁涨价

    P1710 地铁涨价 51通过 339提交 题目提供者洛谷OnlineJudge 标签O2优化云端评测2 难度提高+/省选- 提交  讨论  题解 最新讨论 求教:为什么只有40分 数组大小一定要开够 ...

  9. 洛谷P1371 NOI元丹

    P1371 NOI元丹 71通过 394提交 题目提供者洛谷OnlineJudge 标签云端评测 难度普及/提高- 提交  讨论  题解 最新讨论 我觉得不需要讨论O long long 不够 没有取 ...

随机推荐

  1. asp dotnet core 支持客户端上传文件

    本文告诉大家如何在 asp dotnet core 支持客户端上传文件 新建一个 asp dotnet core 程序,创建一个新的类,用于给客户端上传文件的信息 public class Kanaj ...

  2. H3C网络监测工具命令

    1.Debugging 2.Display debugging 3.Display diagnostic-information display diagnostic-information 命令用来 ...

  3. js实现bind

    Function.prototype.bind=function(ctx,...lastArgs){ let self=this return (...laterArgs)=>self.appl ...

  4. 北京信息科技大学第十一届程序设计竞赛E-- kotori和素因子(深搜)

    链接:https://ac.nowcoder.com/acm/contest/940/E 题目描述 kotori拿到了一些正整数.她决定从每个正整数取出一个素因子.但是,kotori有强迫症,她不允许 ...

  5. JNI相关使用记录

    JNI 工作流程 java层调用system.load方法. 通过classloader拿到了so文件的绝对路径,然后调用nativeload()方法. 通过linux下的dlopen方法,加载并查找 ...

  6. 10款Web前端工具

    10款让Web前端开发人员生活更轻松的实用工具.每个Web开发人员都有自己的工具箱,这样工作中碰到的每个问题都有一个好的解决方案供选择. 对于每一项工作,开发人员需要特定的辅助工具,所以如果下面这些工 ...

  7. Django 中配置MySQL数据库

    在Django的项目中会默认使用sqlite的数据库 配置MySQL需要在setting.py 里加入以下设置: 配置数据库 DATABASES = { 'default': { 'ENGINE': ...

  8. Flask框架知识点整合

    Flask 0.Flask简介 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收ht ...

  9. Spring应用事件(Application Event)

    Spring的事件为Bean与Bean的消息通信提供的支持.当一个Bean处理完了一个任务以后,希望另一个Bean知道并能做出相应的处理,这是我们就需要让另一个Bean监听当前Bean所发送的事件. ...

  10. AnyDesk免费远程工具

    AnyDesk是一款声称速度最快的免费长途衔接/长途桌面操控软件,是前TeamViewer开发小组人员自立门户的商品,它拥有领先的视频压缩技能DeskRT,能够轻松穿透防火墙/路由器,实测在电信.移动 ...