题目
首先,判断是否形成一棵树。因为一共只有n-1条边,如果没有形成树,那一定形成了一个非连通图,并查集所得到的集合个数必然超过1,所以可以用并查集进行判断。
其次,思维过程就是求树的直径,两次dfs(说实话,本菜鸡还是不懂求树的直径的原理,似懂非懂的样子,考完甲级后,认真研究一下)。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n, father[N];
vector<int> G[N];
set<int> temp, ans;
bool isRoot[N];
void init(){
for(int i=1; i<=n; i++){
father[i]=i;
}
}
int findFather(int x){
while(x!=father[x]){
x=father[x];
}
return x;
}
void Union(int a, int b){
int fa=findFather(a);
int fb=findFather(b);
if(fa!=fb){
father[fa]=fb;
}
}
int calBlock(){
memset(isRoot, false, sizeof isRoot);
for(int i=1; i<=n; i++){
isRoot[findFather(i)]=true;
}
int cnt=0;
for(int i=1; i<=n; i++){
cnt+=isRoot[i];
}
return cnt;
}
int maxh=-1;
void dfs(int child, int par, int height){
if(maxh<height){
maxh=height;
temp.clear();
temp.insert(child);
} else if(maxh==height){
temp.insert(child);
}
for(int i=0; i<(int)G[child].size(); i++){
if(G[child][i]==par)
continue;
dfs(G[child][i], child, height+1);
}
}
int main()
{
scanf("%d", &n);
int a, b;
init();
for(int i=1; i<n; i++){
scanf("%d%d", &a, &b);
G[a].push_back(b);
G[b].push_back(a);
Union(a, b);
}
int block=calBlock();
if(block!=1){
printf("Error: %d components\n", block);
} else {
dfs(1, -1, 1);
ans=temp;
dfs(*ans.begin(), -1, 1);
set<int>::iterator it;
for(it=temp.begin(); it!=temp.end(); it++){
ans.insert(*it);
}
for(it=ans.begin(); it!=ans.end(); it++){
printf("%d\n", *it);
}
}
return 0;
}