PAT-A 1021 Deepest Root (25)(25 分)找到使树的高度最大的根

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qian2213762498/article/details/82011843

https://pintia.cn/problem-sets/994805342720868352/problems/994805482919673856

1021 Deepest Root (25)(25 分)

A graph which is connected and acyclic can be considered a tree. The height 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 (<=10000) 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

AC Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int nmax=10000+10;
int father[nmax];
int isRoot[nmax];
vector<int> G[nmax];
 
int findFather(int u){
	if(u==father[u]) return u;
	else{
		int f=findFather(father[u]);
		father[u]=f;
		return f;
	}
}
void Union(int u,int v){
	int fu=findFather(u);
	int fv=findFather(v);
	if(fu!=fv){
		father[fu]=fv;
	}
}
void init(int n){
	for(int i=1;i<=n;i++){
		father[i]=i;
		isRoot[i]=0;
	}
}
int calblk(int n){//计算连通块数目 
	int ans=0;
	for(int i=1;i<=n;i++){
		if(isRoot[findFather(i)]==0){
			isRoot[findFather(i)]++;
			ans+=1;
		}
	}
	return ans;
}

int maxH=0;
vector<int> tmp;//存放DFS的最远节点结果 
vector<int> Ans;//存放答案节点(使树高最大的根节点) 

//u为当前访问的节点编号,h为当前树高,pre为u的父节点 
void DFS(int u,int h,int pre){
    if(h>maxH){
       tmp.clear();
	   tmp.push_back(u);
	   maxH=h;	
    }
    else if(h==maxH){
    	tmp.push_back(u);
	}
	for(int i=0;i<G[u].size();i++){
		if(G[u][i]==pre) continue;//无向图,跳过回去的边 
		DFS(G[u][i],h+1,u); 
	}
} 
 
int main(int argc, char** argv) {
	int n;//点数为n,边数为n-1 
	while(cin>>n){
		memset(father,0,sizeof(father));
		memset(isRoot,0,sizeof(isRoot));
		init(n);
		int u,v;
		for(int i=1;i<=n-1;i++){//n-1条边 
			cin>>u>>v;
			G[u].push_back(v);
			G[v].push_back(u);
			Union(u,v);
		}
		int blk=calblk(n);
		if(blk!=1){//如果不只1个连通块 
			printf("Error: %d components\n",blk);
		}
		else{//如果只有1个连通块 
			DFS(1,1,-1);//u=1,h=1,pre=-1
			Ans=tmp;    //tmp为集合A,赋给Ans 
			DFS(Ans[0],1,-1);//从任意一个根节点开始遍历 
		    for(int i=0;i<tmp.size();i++){
		    	Ans.push_back(tmp[i]); //此时tmp为集合B,将其加到Ans中 
			}
			//求两个集合A、B的并集:先排序,输出值只出现1次的节点 
			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;
}

猜你喜欢

转载自blog.csdn.net/qian2213762498/article/details/82011843
今日推荐