传送门啦

分析:

这个题看起来像是个树形dp,嗯,就是看起来像。

所以我们就按树形dp的思路去分析就好了,这个题是一个树形dp的变形题。

和以前建树是一样的,我们用邻接表来进行储存。利用邻接表的特性,我们可以先加左边的点,再加右边的点,这样遍历的时候就可以先左后右了。

分析题意后我们设立几个数组:

(邻接表的就不说了,大家应该都会吧)

f [ i ] :表示使 i 这棵子树满足条件,所需要的最小的步数。

dep[ i ]:表示 i 这一个点的深度

maxdep[ i ]:表示 i 这个点的子树中风铃的最大深度

mindep[ i ]:同理表示 i 这个点的子树中风铃的最小深度

最后就是怎么样去写转移方程啦。

通过读题我们可以知道,在一棵树一定是一棵二叉树,所以我们就只需要将两棵子树相加就好了。

完成了???

并没有,我们是不是忘记了题目里的条件,题目中要求我们选一个满足下面两个条件的风铃:

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

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

所以我们在状态转移方程里加一个小小的判断

if((abs(maxdep[c[]] - mindep[c[]]) > ) || (abs(mindep[c[]] - maxdep[c[]]) > ) || (maxdep[c[]] > mindep[c[]] && maxdep[c[]] > mindep[c[]])){

    printf("-1");
exit();
}

这次是真的完成了??

是哒

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = ; inline int read(){
int f = , x = ;
char ch = getchar();
while(ch > '' || ch < ''){if(ch == '-')f = -;ch = getchar();}
while(ch >= '' && ch <= ''){x = (x << ) + (x << ) + ch - '';ch = getchar();}
return x * f;
} int n,u,v;
struct Edge{
int from,to,next;
}edge[maxn << ];
int head[maxn],tot;
int f[maxn],w[maxn],cnt,c[maxn],dep[maxn];
int maxdep[maxn],mindep[maxn]; void add(int u,int v){
edge[++tot].from = u;
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot;
} void dfs(int x,int fa){
for(int i=head[x];i;i=edge[i].next){
int v = edge[i].to;
if(v != fa){
dep[v] = dep[x] + ;
dfs(v , x);
mindep[x] = min(mindep[x] , mindep[v]);
maxdep[x] = max(maxdep[x] , maxdep[v]);
}
}
if(w[x] == -)
mindep[x] = maxdep[x] = dep[x];
else {
int num = ;
for(int i=head[x];i;i=edge[i].next){
int v = edge[i].to;
if(v != fa)
c[++num] = v;//两个儿子
}
if((abs(maxdep[c[]] - mindep[c[]]) > )
|| (abs(mindep[c[]] - maxdep[c[]]) > )
|| (maxdep[c[]] > mindep[c[]] && maxdep[c[]] > mindep[c[]])){
printf("-1");
exit();
}
f[x] = f[c[]] + f[c[]] + (mindep[c[]] < maxdep[c[]] ? : );
}
} int main(){
n = read();
cnt = n;
for(int i=;i<=n;i++){
u = read(); v = read();
if(v == -){
v = ++cnt;
w[cnt] = -;
}
add(v , i); add(i , v);
if(u == -){
u = ++cnt;
w[cnt] = -;
}
add(i , u); add(u , i);
}
memset(mindep , 0x3f , sizeof(mindep));
memset(maxdep , , sizeof(maxdep));
dfs( , );
printf("%d\n",f[]);
return ;
}
05-11 01:13