A graph which is connected and acyclic can be considered a tree. The hight of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤104) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N−1 lines follow, each describes an edge by given the two adjacent nodes' numbers.
Output Specification:
For each test case, print each of the deepest roots in a line. If such a root is not unique, print them in increasing order of their numbers. In case that the given graph is not a tree, print Error: K components
where K
is the number of connected components in the graph.
Sample Input 1:
5
1 2
1 3
1 4
2 5
Sample Output 1:
3
4
5
Sample Input 2:
5
1 3
1 4
2 5
3 4
Sample Output 2:
Error: 2 components
【分析】
题意:题目就是要对一个树形结构,找以某个结点为根深度最大的结点,如果有多个,则升序输出。
思路:用并查集(戳这看讲解)求连通分量;用邻接表存储图;
如果图中边的数目远远小于n^2称作稀疏图,这是用邻接表表示比用邻接矩阵表示节省空间;
如果图中边的数目接近于n^2,对于无向图接近于n*(n-1)称作稠密图,考虑到邻接表中要附加链域,采用邻接矩阵表示法为宜。任何连通图的连通分量只有一个,即是其自身
非连通的无向图有多个连通分量。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=10001;
bool vis[maxn];
int a[maxn];//并查集
int n,cnt=0;
vector<int> ma[maxn];//邻接表,理解:是个二维数组
int d[maxn];//深度
int dfs(int s) //如果是连通图,dfs可以一次搜完所有的点
{
int ans=0;
if(vis[s])return 0;
vis[s]=true;
int m=ma[s].size();//每一行的长度
for(int i=0;i<m;i++)
if(!vis[ma[s][i]])
{
int tmp=dfs(ma[s][i]);
ans=max(ans,tmp);
}
return ans+1;
}
void init(int n)//并查集的初始化
{
for(int i=0;i<=n;i++)
a[i]=i;
}
int find(int x)//找根节点
{
if(a[x]!=x)
a[x]=find(a[x]);
return a[x];
}
void join(int x,int y)
{
x=find(x);
y=find(y);
if(a[x]!=a[y])
a[x]=y;
}
int main()
{
int i,j,k,t;
cin>>n;
init(n);
for(i=1;i<n;i++)//题上说的 n-1行
{
int s,e;
cin>>s>>e;
join(s,e);//把连通的两个点,如果不是同跟节点就变成同根节点
ma[s].push_back(e);
ma[e].push_back(s);
}
int sum=0;
for(int i=1;i<=n;i++)//遍历每个节点
if(a[i]==i)sum++; //a是并查集 ,如果某个点的父节点是他本身,则他是一个图的根节点,一个根节点代表一个连通分量
if(sum>1)//连通图最多只有一个连通分量
printf("Error: %d components\n",sum);
else
{
for(i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
d[i]=dfs(i);//深度
}
int maxv=-1,index=0;
for(i=1;i<=n;i++)
if(d[i]>maxv)
{
maxv=d[i];//找最大深度
index=i;
}
for(j=1;j<=n;j++)
if(d[j]==d[index])
printf("%d\n",j);
}
return 0;
}
代码参考:https://blog.csdn.net/u013167299/article/details/44245853