pta--1021 Deepest Root(25 分)(并查集&&邻接表&&dfs)

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 (≤10​4​​) 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

猜你喜欢

转载自blog.csdn.net/qq_38735931/article/details/82143338
今日推荐