您的位置:首页 > 其它

codeforces 765E dfs

2017-02-15 19:46 316 查看
题意:每次从一棵树中找两根长度相同、起点相同的直链并删去其中一根。重复这个操作,求可以得到的最短直链的长度。需要注意的是树即使已经被删成直链了,如果长度是偶数还可以继续删的。



问题的关键是找到树中的“特殊点”,也就是我上面的图中的所有红点。“特殊点”的特点是它的度>2,且与它相连的直链长度不全相等,即以它为起点,不经过其他度>2的点,到达叶子节点的路径有至少两条,且长度不全相等。

容易看出:若特殊点超过1个,结果必是-1;如果上述路径有三种及以上的长度,结果也是-1。不然,结果就是这两种长度之和,然后再除2直到不为偶数。

看出这个结论后就非常简单了:先对任一点建dfs树,用set存起每个点的节点的返回值,如果set.size>=3直接-1,如果==2就说明这个点是特殊点,再以这个点为起点建树做一遍。如果==1说明是普通点,直接+1返回上一层。

此外还需判断没有特殊点的情况。答案不一定直接就是cut(N-1),比如4 4 1 4 2 4 3这组数据,还得瞎搞一下,不再赘述。

#include<stdio.h>
#include<vector>
#include<set>
const int maxn=200020;
std::vector<int>edge[maxn];
int N,q;
int cut(int t){
while(!(t&1))t>>=1;
return t;
}
int dfs(int n,int pre){
int deg=edge
.size();
if(deg==1)return 1;
else if(deg==2)return 1+dfs((pre==edge
[0])?edge
[1]:edge
[0],n);
else{
std::set<int>s;
for(int i=0;i<deg;i++)if(edge
[i]!=pre)
s.insert(dfs(edge
[i],n));
if(s.size()==1)return *s.begin()+1;
if(q)printf("-1\n"),exit(0);
if(pre)q=1,s.insert(dfs(pre,n));
if(s.size()>=3)printf("-1\n"),exit(0);
printf("%d\n",cut(*s.begin()+*s.rbegin()));
exit(0);
};
}
int main(){
scanf("%d",&N);
for(int i=1;i<N;i++){
scanf("%d%d",&u,&v);
edge[u].push_back(v); edge[v].push_back(u);
}
for(int i=1;i<=N;i++)if(edge[i].size()>2)
return 0*printf("%d",cut(dfs(i,0)));
printf("%d",cut(N-1));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces dfs