# Codeforces 765E

RT，这是一道题。。。其实我也不知道为什么就A了

## Codeforces 765E. Tree Folding

### Problem

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.

6
1 2
2 3
2 4
4 5
1 6

3

7
1 2
1 3
3 4
1 5
5 6
6 7

-1

### 代码

#include<set>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#define maxn 200005
using namespace std;
int n,root;
set<int> geo[maxn];
int vis[maxn],exi[maxn],size[maxn];
int f=1,cnt=0,cha=0;
/*set<int> DFS(int x,int depth){
if(geo[x].size()==1&&x!=root){
set<int> cal;
cal.insert(0);
return cal;
}
vis[x]=true;
set<int> cal,k;
for(int i=0;i<geo[x].size();i++){
if(vis[geo[x][i]])continue;
k=DFS(geo[x][i],depth+1);
if(k.size()>2||f==-1){f=-1;k.clear();return k;}
for(set<int>::iterator it=k.begin();it!=k.end();it++){
if(*it+1!=depth)
cal.insert(*it+1);
}
if(cal.size()>2||f==-1){f=-1;cal.clear();return cal;}
}
return cal;
}*/
int DFS(int x){
vis[x]=cnt;
set<int> cal;
stack<int> ans;
int f=0;
for(set<int>::iterator it=geo[x].begin();it!=geo[x].end();it++){
if(vis[*it]==cnt||exi[*it]==0)continue;
f=1;
int k=DFS(*it);
if(k==-1)continue;
if(cal.count(k+1)){
cha=1;
exi[*it]=0;
ans.push(*it);
continue;
}
cal.insert(k+1);
}
while(!ans.empty()){
geo[x].erase(ans.top());
ans.pop();
}
if(f==0){
return 0;
}
if(cal.size()==1){
return *cal.begin();
}
return -1;
}
int DFS2(int x){
vis[x]=cnt;
int k=0;
for(set<int>::iterator it=geo[x].begin();it!=geo[x].end();it++){
if(vis[*it]==cnt)continue;
if(exi[*it]==0)return -1;
k=DFS2(*it);
if(k==-1)return -1;
}
return k+1;
}
int main(){
/*freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);*/
scanf("%d",&n);
int u,v;
for(int i=0;i<n-1;i++){
scanf("%d%d",&u,&v);
geo[u].insert(v);
geo[v].insert(u);
}
for(int i=1;i<=n;i++)
exi[i]=1;
for(;;){
int max1=0,max2;
for(int j=1;j<=n;j++){
if(exi[j]==0)continue;
int op=geo[j].size();
if(max1<op){
max1=op;
max2=j;
}
}
if(max1<=2){
cnt++;
for(int j=1;j<=n;j++){
if(exi[j]==0||vis[j]==cnt||geo[j].size()!=1)continue;
int out=DFS2(j);
if(out!=-1){
out--;
while(out!=0&&out%2==0)out=out/2;
printf("%d",out);
return 0;
}
}
}else{
cnt++;
DFS(max2);
if(cha==0){
printf("-1");
return 0;
}
}
cha=0;
}
/*set<int> k=DFS(root,0);
if(k.size()>1||f==-1)
printf("-1");
else {
int sum=0;
for(set<int>::iterator it=k.begin();it!=k.end();it++){
sum+=*it;
}
printf("%d",sum);
}*/
return 0;
}

## 错点记录

1. 思路有问题

2. set 容器不能在迭代器访问时删点（所以我用stack保存一下要删的点）

3. 未认真思考题意，如本题中的最短长度

4. 未注意避免答案的干扰因素，如本题中将已删去的链当做答案输出

~说实话今天本来想练点DP的，然而并没有一道题是。。。（当然应该是我弱，想不到DP怎么做）CF的标签也是应该好好搞一下了

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120