2021-09-08

题目
首先,判断是否形成一棵树。因为一共只有n-1条边,如果没有形成树,那一定形成了一个非连通图,并查集所得到的集合个数必然超过1,所以可以用并查集进行判断。
其次,思维过程就是求树的直径,两次dfs(说实话,本菜鸡还是不懂求树的直径的原理,似懂非懂的样子,考完甲级后,认真研究一下)。

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n, father[N];
vector<int> G[N];
set<int> temp, ans;
bool isRoot[N];

void init(){
	for(int i=1; i<=n; i++){
		father[i]=i;
	}
}

int findFather(int x){
	while(x!=father[x]){
		x=father[x];
	}

	return x;
}

void Union(int a, int b){
	int fa=findFather(a);
	int fb=findFather(b);
	if(fa!=fb){
		father[fa]=fb;
	}
}

int calBlock(){
	memset(isRoot, false, sizeof isRoot);
	for(int i=1; i<=n; i++){
		isRoot[findFather(i)]=true;
	}

	int cnt=0;
	for(int i=1; i<=n; i++){
		cnt+=isRoot[i];
	}

	return cnt;
}

int maxh=-1;
void dfs(int child, int par, int height){
	if(maxh<height){
		maxh=height;
		temp.clear();
		temp.insert(child);
	} else if(maxh==height){
		temp.insert(child);
	}

	for(int i=0; i<(int)G[child].size(); i++){
		if(G[child][i]==par)
			continue;

		dfs(G[child][i], child, height+1);
	}
}

int main()
{
    scanf("%d", &n);
    int a, b;
    init();
    for(int i=1; i<n; i++){
    	scanf("%d%d", &a, &b);
    	G[a].push_back(b);
    	G[b].push_back(a);
        Union(a, b);
    }

    int block=calBlock();
    if(block!=1){
    	printf("Error: %d components\n", block);
    } else {
    	dfs(1, -1, 1);
    	ans=temp;
    	dfs(*ans.begin(), -1, 1);
    	set<int>::iterator it;
    	for(it=temp.begin(); it!=temp.end(); it++){
    		ans.insert(*it);
    	}

    	for(it=ans.begin(); it!=ans.end(); it++){
    		printf("%d\n", *it);
    	}
    }
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值