很好的图遍历的入门题
看题目戳这
主要是这个图有两个性质
1、如果图有n个节点,有n-1条边,且只有一个连通块,那么这个图就是树
2、符合1的图,从任意一个节点遍历,所能获得的最深节点设为A集合(最深的意思就是遍历不下去的那种点,想不明白继续举例想),然后再从A集合里的任意一个点遍历一遍,所能获得的最深节点设为B集合,那么A∪B的所有节点都是所要的答案。
(证明见算法笔记上机训练,其实我也没看证明)
代码如下呀
#include<bits/stdc++.h>
using namespace std;
int fa[10005],maxh,n;
bool isroot[10005];
vector<int> ans,temp,G[10005];
int get(int x){
if(x==fa[x]){
return x;
}
return fa[x]=get(fa[x]);
}
int merge(int x,int y){
return fa[get(fa[x])]=get(fa[y]);
}
int getblock(){
int res=0;
for(int i=1;i<=n;i++){
isroot[get(fa[i])]=1;
}
for(int i=1;i<=n;i++){
res+=isroot[i];
}
return res;
}
void dfs(int u,int h,int aga){
if(h>maxh){
temp.clear();
temp.push_back(u);
maxh=h;
}else if(h==maxh){
temp.push_back(u);
}
for(int i=0;i<G[u].size();i++){
if(G[u][i]==aga){
continue;
}
dfs(G[u][i],h+1,u);
}
}
int main(){
int a,b;
scanf("%d",&n);
for(int i=1;i<=n;i++){
fa[i]=i;
}
for(int i=0;i<n-1;i++){
scanf("%d%d",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
merge(a,b);
}
if(getblock()!=1){
printf("Error: %d components\n",getblock());
return 0;
}
dfs(1,0,-1);
ans=temp;
dfs(ans[0],0,-1);
for(int i=0;i<temp.size();i++){
ans.push_back(temp[i]);
}
sort(ans.begin(),ans.end());
printf("%d\n",ans[0]);
for(int i=1;i<ans.size();i++){
if(ans[i]!=ans[i-1]){
printf("%d\n",ans[i]);
}
}
return 0;
}