PAT (Advanced Level) Practice 1021 Deepest Root (25 分)

  • 编程题

1021 Deepest Root (25 分)

A graph which is connected and acyclic can be considered a tree. The hight 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 (≤10​4​​) 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

题目大意:

给出节点数和边,求它是不是一棵树。如果不是,求它有几个独立模块;如果是,求使这棵树高度最大的根节点。

解题思路:

先用 dfs 求一共有几个独立模块。深搜的同时记录最大高度和该高度上的所有子节点。

如果只有一个独立模块,把最大高度的所有子节点记录下来。再从这些子节点中随意选择一个子节点作为根节点,重新做一次深搜,记录最大高度的所有子节点。使用set求这两个子节点集合的并集,set自动从小到大排序输出。

注意事项:

1、刚开始采用建图的方法(e[10001][10001]),导致内存超限。改用向量数组,通过了测试点;

2、求两个子节点集合的并集时,本来是用向量数组记录,再排序,再从小到大输出不重复的项(因为也许两个集合中有相同的节点),这个方法比较麻烦。改用set,自动排除重复项,自动排序,方便许多;

3、set输出用 for(auto it = ans.begin(); it != ans.end(); it++) printf("%d\n", *it); 不能直接 ans[i] 输出。

4、book[10001]发生段错误,改成book[10002]后通过测试。。。

源代码:

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<set>
using namespace std;
const int inf = 99999999;
int n, book[10010] = { 0 }, maxlevel = 0;
vector<vector<int>>e;
vector<int>root;
set<int>ans;
bool cmp(int a, int b) { return a < b; }
void dfs(int r, int c, int level)
{
	book[r] = c;
	if (level > maxlevel)
	{
		maxlevel = level;
		root.clear();
		root.push_back(r);
	}
	else if (level == maxlevel)
		root.push_back(r);
	for (int j = 0; j < e[r].size(); j++)
	{
		if (book[e[r][j]] == 0)dfs(e[r][j], c, level + 1);
	}
	return;
}
int main()
{
	int i, j, k, a, b, cnt;
	scanf("%d", &n);
	e.resize(n + 1);
	for (i = 1; i < n; i++)
	{
		scanf("%d %d", &a, &b);
		e[a].push_back(b);
		e[b].push_back(a);
	}
	cnt = 0;
	for (i = 1; i <= n; i++)
	{
		if (book[i] == 0)
		{
			cnt++;
			dfs(i, cnt, 0);
		}
	}
	if (cnt > 1)printf("Error: %d components", cnt);
	else
	{
		for (i = 0; i < root.size(); i++)ans.insert(root[i]);
		int r0 = root[0];
		root.clear();
		maxlevel = 0;
		for (i = 1; i <= n; i++)book[i] = 0;
		dfs(r0, cnt, 0);
		for (i = 0; i < root.size(); i++)ans.insert(root[i]);
		for (auto it=ans.begin(); it!=ans.end(); it++)
		{
			printf("%d\n", *it);
		}
	}
	system("pause");
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值