PAT甲级 1021. Deepest Root

113 篇文章 9 订阅
110 篇文章 12 订阅

1021. Deepest Root (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
题目大意:给出n个结点(1~n)之间的n条边,问是否能构成一棵树,如果不能构成则输出它有的连通分量个数,如果能构成一棵树,输出能构成最深的树的高度时,树的根结点。如果有多个,按照从小到大输出。
分析:首先深度优先搜索判断它有几个连通分量。如果有多个,那就输出Error: x components,如果只有一个,就两次深度优先搜索,先从一个结点dfs后保留最高高度拥有的结点们,然后从这些结点中的其中任意一个开始dfs得到最高高度的结点们,这两个结点集合的并集就是所求

解法一:此方法用vector<vector<int> edge来存储边,避免了内存不超过

#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<set>
using namespace std;

const int maxsize = 10001;
int n,e;
bool visited[maxsize];
vector<vector<int>> edge;
int maxheight=-1;

 

vector<int> temp;
set<int> myset;

void dfs(int v,int height){	
	if(height>maxheight){
		maxheight = height;
		temp.clear();
		temp.push_back(v);
	}else if(height == maxheight){
		temp.push_back(v);
	}
	
	visited[v] = 1;
	
	for(int i=0;i<edge[v].size();i++){//注意,这里是通过下标,所以是从0开始 
		if(visited[edge[v][i]]==0){
			dfs(edge[v][i],height+1);
		}
	}
}

int main(){
	memset(visited,0,sizeof(visited));
	
	cin>>n;
	edge.resize(n+1);
	
	e = n-1;
	for(int i=1;i<=e;i++)
	{
		int a,b;
		cin>>a>>b;
		edge[a].push_back(b);//通过下标读取一个vector 
		edge[b].push_back(a);
	}
	
	int cnt = 0;
	for(int i=1;i<=n;i++){
		if(!visited[i]){
			cnt++;
			dfs(i,1);
		}
	}
	
	if(cnt>=2){
		cout<<"Error: "<<cnt<<" components";
		return 0;
	}
	
	for(auto it:temp){//先把最深的点加进来,再以这其中的一个顶点再进行一次DFS 
		myset.insert(it);
	}
	
	memset(visited,0,sizeof(visited));
	int node = temp[0];
	temp.clear(); 
	dfs(node,1);
	
	for(auto it:temp){
		myset.insert(it);
	}
	
	for(auto it:myset){
		cout<<it<<endl;
	}	
	
	return 0;
}

解法二:通过常规二维矩阵来存储edge

#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<set>
using namespace std;

const int maxsize = 10001;
int n,e;
bool visited[maxsize];
int edge[maxsize][maxsize];
int maxheight=-1; 

vector<int> temp;
set<int> myset;

void dfs(int v,int height){
	visited[v] = 1;
	
	if(height>maxheight){
		maxheight = height;
		temp.clear();//先清空 
		temp.push_back(v);
	}else if(height == maxheight){
		temp.push_back(v);
	}
	
	for(int i=1;i<=n;i++){
		if(edge[v][i]==1 && visited[i]==0){
			dfs(i,height+1);
		}
	}
}

int main(){
	memset(visited,0,sizeof(visited));
	
	cin>>n;
	e = n-1;
	for(int i=1;i<=e;i++)
	{
		int a,b;
		cin>>a>>b;
		edge[a][b] = edge[b][a] = 1;
	}
	
	int cnt = 0;
	for(int i=1;i<=n;i++){
		if(!visited[i]){
			cnt++;
			dfs(i,1);
		}
	}
	
	if(cnt>=2){
		cout<<"Error: "<<cnt<<" components";
		return 0;
	}
	
	for(auto it:temp){//先把最深的点加进来,再以这其中的一个顶点再进行一次DFS 
		myset.insert(it);
	}
	
	int node = temp[0];
	temp.clear();//重新dfs前要清空 
	memset(visited,0,sizeof(visited));//再次置0 
	dfs(node,1);//选择第一次dfs中任意一个最深的结点作为第二次dfs起点即可 
	
	for(auto it:temp){
		myset.insert(it);
	}
	
	for(auto it:myset){
		cout<<it<<endl;
	}	
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值