E. Tree Folding
题目连接:
http://codeforces.com/contest/765/problem/E
Description
Vanya wants to minimize a tree. He can perform the following operation multiple times: choose a vertex v, and two disjoint (except for v) paths of equal length a0 = v, a1, …, ak, and b0 = v, b1, …, bk. Additionally, vertices a1, …, ak, b1, …, bk must not have any neighbours in the tree other than adjacent vertices of corresponding paths. After that, one of the paths may be merged into the other, that is, the vertices b1, …, bk can be effectively erased:
Help Vanya determine if it possible to make the tree into a path via a sequence of described operations, and if the answer is positive, also determine the shortest length of such path.
Input
The first line of input contains the number of vertices n (2 ≤ n ≤ 2·105).
Next n - 1 lines describe edges of the tree. Each of these lines contains two space-separated integers u and v (1 ≤ u, v ≤ n, u ≠ v) — indices of endpoints of the corresponding edge. It is guaranteed that the given graph is a tree.
Output
If it is impossible to obtain a path, print -1. Otherwise, print the minimum number of edges in a possible path.
Sample Input
6
1 2
2 3
2 4
4 5
1 6
Sample Output
3
Hint
题意
给你一棵树,可以在这棵树上进行若干次操作,每次操作可以把两条相同的链,根据一个中点合并在一起,具体看题目的图片(CF上面)
然后问你经过若干次合并之后,最后的最短链长度是多少。
如果不能合并成一条链,输出-1.
题解:
拓扑排序,每次我们从度数为1的点出发bfs。
然后往上合并,如果遇到交叉点,我们就合并链。
我们用一个set来合并就好了,如果两条链长度一样,在set里面自动就合并了。
显然能够bfs的点的set里面只有一个数。
而且只能有一个点的set里面有两个数。
最后扫一遍check一下就好了。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+7;
vector<int> E[maxn];
int n,vis[maxn],len[maxn],de[maxn],d[maxn];
set<int> S[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
E[a].push_back(b);
E[b].push_back(a);
d[a]++;
d[b]++;
}
queue<int> Q;
for(int i=1;i<=n;i++){
if(E[i].size()==1){
Q.push(i);
S[i].insert(0);
}
}
while(!Q.empty()){
int now = Q.front();
vis[now]=1;
Q.pop();
for(int i=0;i<E[now].size();i++){
int v = E[now][i];
if(vis[v])continue;
S[v].insert((*S[now].begin())+1);
d[v]--;
if(d[v]==1&&S[v].size()==1){
Q.push(v);
}
}
}
int ans = 0,num2 = 0;
for(int i=1;i<=n;i++){
if(S[i].size()==0){
cout<<"-1"<<endl;
return 0;
}
if(S[i].size()>2){
cout<<"-1"<<endl;
return 0;
}
if(S[i].size()==1){
ans=max(ans,*S[i].begin());
}
if(S[i].size()==2){
ans=max(ans,*S[i].begin()+*S[i].rbegin());
num2++;
}
}
if(num2>1){
cout<<"-1"<<endl;
return 0;
}
while(ans%2==0){
ans/=2;
}
cout<<ans<<endl;
}