[PAT-A 1021]Deepest Root

在这里插入图片描述
题目大意:
给出N个节点和N-1条边,问它们能否形成一颗N个节点的树,如果能,则从中选出节点作为树根,使得可以得到的树的高度最大

思路:
1.判断图是否联通,可以使用dfs或者并查集,每次读入一条边和两个端点,判断这两个端点是否属于相同的集合,即集合根节点是否相同,如果不同,将它们合并到一个集合中去,处理完之后判断产生集合的个数是否为1来判断给定的图是否联通。
2.当图联通时,由于题目保证只有N-1条边,因此即为一棵树,然后选择一个节点 ,使得数的高度最大,选择过程如下:
1)先任意选择一个节点,从该节点出出发遍历整棵树,获取能达到最深的顶点记为集合A。
2)从集合A中任意一个节点出发遍历整棵树,获取能够到达的最深的节点,记为集合B。
3)求A与B的并集即为所求最大树高的根节点。
3.图是无向图,因此会在临界表中同时存放两个方向的边,在遍历的时候要记录当前节点的前驱节点,防止出现走回头路。
4.当N=1时输出1.
5.邻接矩阵存储会超时。

AC代码:

//PAT_A 1021
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 100010;
vector<int> G[maxn];//邻接表
bool isRoot[maxn];
int father[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 faA = findFather(a);
	int faB = findFather(b);
	if (faA != faB)father[faA] = father[faB];
}
void init(int n) {//初始化
	for (int i = 1; i <= n; i++) {
		father[i] = i;
	}
}
int calBlock(int n) {
	int block = 0;
	for (int i = 1; i <= n; i++) {
		isRoot[findFather(i)] = true;
	}
	for (int i = 1; i <= n; i++) {
		block += isRoot[i];
	}
	return block;	
}
int maxH = 0;
vector<int> temp, ans;
void dfs(int u, int height, int pre) {//u 当前访问节点编号,height 当前树高,pre u的父亲节点
	if (height > maxH) {//更新最大高度
		temp.clear();
		temp.push_back(u);
		maxH = height;
	}
	else if (height == maxH)temp.push_back(u);
	for (int i = 0; i < G[u].size(); i++) {
		if (G[u][i] == pre)continue;//跳过回去的边
		dfs(G[u][i], height + 1, u);
	}
}
int main() {
	int a, b, n;
	(void)scanf("%d", &n);
	init(n);
	for (int i = 1; i < n; i++) {
		(void)scanf("%d %d", &a, &b);
		G[a].push_back(b);
		G[b].push_back(a);
		Union(a, b);
	}
	int block = calBlock(n);
	if (block != 1) printf("Error: %d components\n", block);
	else {
		dfs(1, 1, -1);//从1号节点开始遍历
		ans = temp;
		dfs(ans[0], 1, -1);//从任意节点开始遍历
		for (int i = 0; i < temp.size(); i++) {
			ans.push_back(temp[i]);//取并集
		}
		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;
}
发布了142 篇原创文章 · 获赞 1 · 访问量 4563

猜你喜欢

转载自blog.csdn.net/weixin_44699689/article/details/104587158