https://codeforces.com/contest/1182/problem/D
思路:按照满足题意的点拎起来的图大概就是这样
答案只能是树的直径的两点或者直径的中间点,或者直径中间点的最近的叶子节点。橙色紫色或者直径的两端。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define FI first
#define SE second
#define MP make_pair
const LL mod =1e9+7;
const int MX = 1e5+5;
vector<int>g[MX];
int pr[MX];
vector<int>samede[MX];
set<int> bfs(int st){
set<int> re;
queue<pair<int,int> >q;q.push(MP(st,1));pr[st]=-1;
int ed=-1,step=-1;
while(!q.empty()){//从1到最远x
auto now=q.front();q.pop();
ed=now.FI;step=now.SE;
for(int i:g[now.FI]){
if(pr[i]!=0)continue;
pr[i]=now.FI;
q.push(MP(i,now.SE+1));
}
}
re.insert(ed);
st=ed;memset(pr,0,sizeof(pr));
q.push(MP(st,1));pr[st]=-1;
while(!q.empty()){ //从x到最远y
auto now=q.front();q.pop();
ed=now.FI;step=now.SE;
for(int i:g[now.FI]){
if(pr[i]!=0)continue;
pr[i]=now.FI;
q.push(MP(i,now.SE+1));
}
}
re.insert(ed);
for(int i=1;i<=step/2;i++)
ed=pr[ed];
re.insert(ed);
st=ed;memset(pr,0,sizeof(pr));
q.push(MP(st,1));pr[st]=-1;
while(!q.empty()){ //从x和y的中点到最近的叶子节点
auto now=q.front();q.pop();
ed=now.FI;step=now.SE;
if((int)g[now.FI].size()==1)break;
for(int i:g[now.FI]){
if(pr[i]!=0||g[i].size()>2)continue;
pr[i]=now.FI;
q.push(MP(i,now.SE+1));
}
}
re.insert(ed);
return re;
}
void dfs(int rt,int de,int fa){
samede[de].push_back(rt);
for(int i:g[rt]){
if(i==fa)continue;
dfs(i,de+1,rt);
}
}
bool ju(int rt){
dfs(rt,1,-1);int tag=1;
for(int i=1;i<MX;i++){
if((int)samede[i].size()<2) {samede[i].clear();continue;}
for(int j=1;j<(int)samede[i].size();j++){
if(g[samede[i][j]].size()!=g[samede[i][j-1]].size())
tag=0;
}
samede[i].clear();
}
return tag;
}
int main(){
int n;cin>>n;for(int i=1;i<n;i++){
int aa,bb;scanf("%d%d",&aa,&bb);
g[aa].push_back(bb);g[bb].push_back(aa);
}
auto zz=bfs(1); //返回一个set,存了直径两点,中间点,和中间点到最近的叶子节点
for(auto i:zz){
if(ju(i)) {printf("%d\n",i);return 0;}
}
puts("-1");
return 0;
}