PAT (Advanced Level) 1021. Deepest Root (25) 并查集+DFS

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
使用并查集判断子图数目。
若子图数为1,对每个结点进行dfs可得到最大深度的点。这种写法有一个case超时。
为了避免大数据超时,只使用两次dfs,第一次对结点1进行dfs,得到一个候选结点集合tbd,第二次对候选结点集合中的随意一个结点进行dfs,得到第二个候选结点集合tbd1,对两个集合进行合并和去重即为结果。(事实上本题可以转换为:对于以1号结点为根的树,输出树中相距最远的两个结点,若有多个结果,将满足条件的结点从小到大输出。易知对根结点进行1次dfs,最深的叶子结点肯定是候选结点,若这些叶子结点分布在根结点的两个子树,则相互匹配;若这些叶子结点分布在根结点的同一颗子树,则其匹配的结点可能在根结点的另一棵子树,这就是原题进行第二次dfs的原因)
<pre name="code" class="cpp">/*2015.7.22cyq*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
using namespace std;

//ifstream fin("case1.txt");
//#define cin fin

int findroot(vector<int> &root,int a){
	if(root[a]!=a)
		root[a]=findroot(root,root[a]);//路径压缩,将多跳后的根作为a的直接上级
	return root[a];
}
int graphNum(const vector<vector<bool> > &edges,int N){
	vector<int> root;
	for(int i=0;i<=N;i++)
		root.push_back(i);//一开始每个结点的根结点都是自身 
	int result=N; //最多有N个子图
	for(int i=1;i<=N;i++){
		for(int j=i+1;j<=N;j++){
			if(edges[i][j]){
				int ar=findroot(root,i);
				int br=findroot(root,j);
				if(ar!=br){//不在同一个子图
					result--;//该边使得子图数减一
					root[ar]=br;//连接两个子图
				}
			}
		}
	}
	return result;
}
void dfs(vector<vector<bool> > &edges,int &N,int start,int &depth,int &maxD,vector<int> &tbd){
	depth++;
	if(depth>maxD){
		maxD=depth;
		tbd.clear();
		tbd.push_back(start);
	}else if(depth==maxD){
		tbd.push_back(start);
	}
	for(int i=1;i<=N;i++){
		if(edges[start][i]){
			edges[start][i]=false;
			edges[i][start]=false;
			dfs(edges,N,i,depth,maxD,tbd);
			edges[start][i]=true;
			edges[i][start]=true;
		}
	}
	depth--;
}
int main(){
	int N;
	cin>>N;
	if(N==1){
		cout<<1;
		return 0;
	}
	vector<vector<bool> > edges(N+1,vector<bool>(N+1,false));
	int a,b;
	for(int i=1;i<N;i++){
		cin>>a>>b;
		edges[a][b]=true;
		edges[b][a]=true;
	}
	int gn=graphNum(edges,N);
	if(gn>1){
		printf("Error: %d components",gn);
		return 0;
	}

	

	//对1号结点进行一次dfs,
	int start=1;//dfs起点
	int depth=0;//dfs中动态变化的深度
	int maxD=0;//最大深度
	vector<int> tbd;//存储候选结点
	dfs(edges,N,start,depth,maxD,tbd);
	int deptest=maxD;//记录最大深度

	
	//对其中一个候选结点进行dfs
	start=tbd[0];
	depth=0;
	maxD=0;
	vector<int> tbd1;
	dfs(edges,N,start,depth,maxD,tbd1);

	for(auto it=tbd1.begin();it!=tbd1.end();++it)
		tbd.push_back(*it);
	
	sort(tbd.begin(),tbd.end());
	tbd.resize(unique(tbd.begin(),tbd.end())-tbd.begin());
	for(auto it=tbd.begin();it!=tbd.end();it++)
		cout<<*it<<endl;
	return 0;
}


 

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值