PAT-图的遍历-1021 Deepest Root

94 阅读1分钟

思路一

  • 用layer[]存储叶节点的最大高度,同时叶节点只会是vector大小为1的节点。
  • 判断是不是树只需要判断非连通图的个数即可,可以用并查集和vis[]数组的方法。

思路二

  • 任意节点距离最远的点一定是deepest root的集合(证明见算法笔记)
  • 从任意一个点遍历得到根集合temp1,从根集合temp1选出一个点遍历的集合temp2,两者的并集即为所求。

注意

  • 如果图是无环图,不需要使用vis[]来进行dfs,只需在遍历到前节点时跳过即可。
  • n等于1时,输出1。
  • 可以使用set,会使题目更加简单。

代码一

#include<vector>
#include<algorithm>
using namespace std;
const int maxn=10001;
int n,maxk=0;
vector<int> adj[maxn];
bool vis[maxn]={false};
int layer[maxn];

void BFS(int u,int dep){
	if(dep>layer[u]) layer[u]=dep;   //求每个结点的最高高度 
	if(dep>maxk) maxk=dep;           //找出最高高度 
	vis[u]=true;
	for(int i=0;i<adj[u].size();i++){
		int v=adj[u][i];
		if(vis[v]==false){
			BFS(v,dep+1);
		}
	}
}

void initial(){
	for(int i=1;i<=n;i++){
		vis[i]=false;
	}
}

int BFSTrave(){           //判断是不是树 
	int ans=0; 
	for(int i=1;i<=n;i++){
		if(vis[i]==false){
			BFS(i,0);
			ans++;
		}
	}
	return ans;
}
void BFSTrave2(){   //判断每个叶子结点的最大高度 
	for(int i=1;i<=n;i++){
		initial();
		if(adj[i].size()==1){
			BFS(i,0);
		}
	}
}
int main(){
	scanf("%d",&n);
	int a,b;
	for(int i=0;i<n-1;i++){
		scanf("%d%d",&a,&b);
		adj[a].push_back(b);
		adj[b].push_back(a);
	}
	int num=BFSTrave();
	if(num==1){
		BFSTrave2();
		for(int i=1;i<=n;i++){
			if(layer[i]==maxk) printf("%d\n",i);
		}
	}
	else {
		printf("Error: %d components",num);
	}
	return 0;
}

代码二

#include<vector>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=10010;
vector<int> adj[maxn];
int n,maxk=0;

int father[maxn];
bool isroot[maxn];
int findFather(int x){
	int a=x;
	while(x!=father[x]){
		x=father[x];
	}
	while(a!=father[a]){
		int z=a;
		a=father[a];
		father[z]=x;
	}
	return x;
} 
void Union(int a,int b){
	int fa=findFather(a);
	int fb=findFather(b);
	if(fa!=fb){
		father[fa]=fb;
	}
}
void initial(){
	for(int i=1;i<=n;i++){
		father[i]=i;
	}
}
int calblock(){
	int ans=0;
	for(int i=1;i<=n;i++){
		isroot[findFather(i)]=true;
	}
	for(int i=1;i<=n;i++){
		ans+=isroot[i];
	}
	return ans;
}

set<int> temp,ans;
void DFS(int u,int dep,int pre){
	if(dep>maxk){
		temp.clear();
		temp.insert(u);
		maxk=dep;
	}
	if(dep==maxk){
		temp.insert(u);
	}
	for(int i=0;i<adj[u].size();i++){
		if(adj[u][i]==pre) continue;  //只能用在无环树 
		DFS(adj[u][i],dep+1,u);
	}
}
int main(){
	int a,b;
	scanf("%d",&n);
	initial();
	for(int i=0;i<n-1;i++){
		scanf("%d%d",&a,&b);
		adj[a].push_back(b);
		adj[b].push_back(a);
		Union(a,b);
	}
	int num=calblock();
	if(num!=1) printf("Error: %d components",num);
	else{
		DFS(1,1,-1);
		ans=temp;
		set<int>::iterator it=ans.begin();
		maxk=0;
		DFS(*it,1,-1);
		for(;it!=ans.end();it++){
			temp.insert(*it);
		}
		int pre=-1;
		for(set<int>::iterator it=temp.begin();it!=temp.end();it++){
			if(*it!=pre) printf("%d\n",*it);
			pre=*it;
		}
	}
	return 0;
}