A1021 Deepest Root (25分)

一、技术总结

  1. 这一题题目很好理解,就是求一个图如果只有一个连通块,那么就可以被当做tree,然后要求出所有结点中如果被选中作为根结点,能达到的最大高度,如果有多个按照从小到大的顺序输出。如果有多个连通块,直接输出题目中的要求。
  2. 但是开始自己写想思路不清晰,也是想就是正常思路,判断深度,然后记录,统计连通分量的数量。最后直接爆炸了。
  3. 后来知道,可以首先通过一次dfs遍历图一遍,然后统计出当前结点下所有最大深度的叶子结点们,然后再其中任选一个结点,重新遍历一次,统计出一次当前结点下所有最大深度的叶子结点们,然后这连个集合的并集就是答案。这里使用set集合,可以方便的得出答案。这个可以作为结论记下来。这一点是整个题目解题的关键,如果这里没有理解,就会理解不了代码,可以自己画个小图,试一下看结论是否正确。

二、参考代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 10010;
int n, maxheight = 0;
vector<int> v[maxn];//邻接表 
bool visit[maxn] = {false};//判断是否已经访问过 
set<int> s;//这是可以自动排序 
vector<int> temp;//用于存储具有最大相同高度的结点们 
void dfs(int node, int height){
	//这一部分是判断当前结点是否是最大高度 
	if(height > maxheight){
		temp.clear();
		temp.push_back(node);
		maxheight = height;
	}else if(height == maxheight){
		temp.push_back(node);
	}
	visit[node] = true;
	for(int i = 0; i < v[node].size(); i++){
		if(visit[v[node][i]] == false){
			dfs(v[node][i], height+1);
		}
	} 
}
int main(){
	scanf("%d", &n);
	//v.resize(n+1);//
	int a, b, cnt = 0, s1 = 0;//cnt记录连通块的数量,s1标记为可以访问到最大高度
	for(int i = 0; i < n -1; i++){
		scanf("%d %d", &a, &b);
		v[a].push_back(b);
		v[b].push_back(a);
	} 
	for(int i = 1; i <= n; i++){
		if(visit[i] == false){
			dfs(i, 1);
			if(i == 1){
				if(temp.size() != 0) s1 = temp[0];
				for(int j = 0; j < temp.size(); j++){
					s.insert(temp[j]);
				}											
			}
			cnt++;
		}
	}
	if(cnt >= 2){
		printf("Error: %d components", cnt);
	}else{
		temp.clear();
		maxheight = 0;
		fill(visit, visit+maxn, false);
		dfs(s1, 1);
		for(int i = 0; i < temp.size(); i++){
			s.insert(temp[i]);
		}
		for(auto it = s.begin(); it != s.end(); it++){
			printf("%d\n", *it);
		}
	}
	return 0;
}
posted @ 2020-02-28 16:17  睿晞  阅读(123)  评论(0编辑  收藏  举报