题⽬⼤意:给出n个结点(1~n)之间的n条边,问是否能构成⼀棵树,如果不能构成则输出它有的连
通分量个数,如果能构成⼀棵树,输出能构成最深的树的⾼度时,树的根结点。如果有多个,按照从
⼩到⼤输出。
思路:首先并查集判断联通分块的数量,只有一个联通分量,选择任意一个节点,到达最深的节点(记为节点集A),然后从A里面任意选择一个节点,到达最深的节点(记为节点集B),A和B的并集就是能够使树最高的节点。bfs好像会超内存。
柳神代码的思想:用dfs来判断联通块的数量,然后基本一样,代码要简短很多。
#include<stdio.h>
#include<iostream>
#include<vector>
#include<set>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
int n;
vector<int> g[10007];//图
int v[10007];
int father[10007];
set<int> st;
vector<int> res;
int maxheight=-1;
int find(int x)
{
if(x==father[x])
return x;
else
return find(father[x]);
}
//void bfs(int x)
//{
// queue<int> q;
// q.push(x);
// v[x]=true;
// while(!q.empty())
// {
// int k=q.front();
// if(ans==n)
// {
// while(!q.empty())
// {
// st.insert(q.front());
// q.pop();
// }
// break;
// }
// for(int i=0;i<g[k].size();i++)
// {
// if(v[g[k][i]]==false)
// {
// q.push(g[k][i]);
// ans++;
// }
// }
// q.pop();
// }
// return ;
//}
void dfs(int x,int height)
{
v[x]=true;
if(height>maxheight)
{
res.clear();
res.push_back(x);
maxheight=height;
}
else if(height==maxheight)
res.push_back(x);
for(int i=0;i<g[x].size();i++)
{
if(v[g[x][i]]==false)
dfs(g[x][i],height+1);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
father[i]=i;
int a,b;
for(int i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
g[a].push_back(b);
g[b].push_back(a);
int x=find(a);
int y=find(b);
if(x!=y)
father[x]=y;
}
int cnt=0;
for(int i=1;i<=n;i++)
{
if(father[i]==i)
cnt++;
}
if(cnt!=1)
{
printf("Error: %d components",cnt);
}
else
{
// bfs(1);
// memset(v,false,sizeof(v));
// set<int>::iterator it=st.begin();
// bfs(*it);
dfs(1,0);
for(int i=0;i<res.size();i++)
st.insert(res[i]);
memset(v,false,sizeof(v));
int kk=res[0];
res.clear();
dfs(kk,0);
for(int i=0;i<res.size();i++)
st.insert(res[i]);
for(set<int>::iterator it=st.begin();it!=st.end();it++)
{
printf("%d\n",*it);
}
}
return 0;
}