1021 Deepest Root (25分)

1.可以用并查集求无向图的连通图个数,也可以直接用dfs  然后要注

2.若是树   则相当于求树的最大直径    即 第一次dfs求出部分直径端点   第二次求出所有的直径端点

3.用set去重   不然好麻烦

 

//树的最大直径 :先用任一端点找出直径的一个端点   然后用该端点求出直径的其余端点
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<set>

using namespace std;

const int N = 10000+5;
vector<int> V[N], ans;
set<int> temp;
bool vis[N];
int pre[N];
int cnt;//连通分量个数
int Maxh= 1;
void init() {
	ans.clear();
	for(int i=0; i<N; i++) {
		V[i].clear();
		vis[i] = false;
		pre[i] = i;
	}
}
//用并查集求连通分量个数(需是无向图)
int Find(int a) {
	return (a == pre[a])? a : (pre[a] = Find(pre[a]));
}
bool Union(int a, int b) {
	a = Find(a), b = Find(b);

	if(a == b) { //本就在一起
		return false;
	} else {
		pre[a] = b;
		return true;
	}
}

void dfs(int a, int h) {
	vis[a] = true;

	if(h >= Maxh) {
		if(h > Maxh) {
			ans.clear();
		}
		//	cout << h << "==" << Maxh <<"::"<< ans.size() << endl;
		Maxh = h;
		ans.push_back(a);
	}
	for(int i=0; i<V[a].size(); i++) {
		if(!vis[V[a][i]]) {
			dfs(V[a][i], h+1);
		}
	}
}
int main() {
	int n;
	init();
	cin >> n;
	cnt = n;
	for(int i=0; i<n-1; i++) {
		int a, b;
		cin >> a >> b;
		V[a].push_back(b);
		V[b].push_back(a);

		if(Union(a, b)) {
			cnt--;
		}
	}

	if(cnt > 1) {
		printf("Error: %d components\n", cnt);
	} else { //求树的最大直径  以及直径的端点
		dfs(1, 1);//先求出一个端点
		int tmp = ans[0];
		memset(vis, false, sizeof(vis));
		
		for(int i=0; i<ans.size(); i++){
			temp.insert(ans[i]);
		}
		ans.clear();
		dfs(tmp, 1);
		ans.push_back(tmp);
		
		for(int i=0; i<ans.size(); i++){
			temp.insert(ans[i]);
		}
		
		for(set<int>:: iterator it=temp.begin(); it!=temp.end(); it++) {
			cout << *it << endl;
		}
	}


	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值