问题 B: 会议------------------------------思维(树的重心+dfs/bfs+套路题)

题目描述
有一个村庄居住着n个村民,有n-1条路径使得这n个村民的家联通,每条路径的长度都为1。现在村长希望在某个村民家中召开一场会议,村长希望所有村民到会议地点的距离之和最小,那么村长应该要把会议地点设置在哪个村民的家中,并且这个距离总和最小是多少?若有多个节点都满足条件,则选择节点编号最小的那个点。
输入
第一行。一个数n,表示有n个村民。
接下来n-1行,每行两个数字a和b,表示村民a的家和村民b的家之间存在一条路径。

输出
一行输出两个数字x和y
x表示村长将会在哪个村民家中举办会议
y表示距离之和的最小值

样例输入 Copy
4
1 2
2 3
3 4
样例输出 Copy
2 4
提示
70%数据n<=1000
100%数据n<=50000

解析:
突破口:找到一点,使得其他点到他的距离之和最小
套路题,树的重心
在这里插入图片描述

所以我们dp求解树的重心。
然后dfs求其他点到重心的距离。或者bfs求都可以
下面写了bfs求距离的,注释掉的是dfs求距离。

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
vector<int> G[N];
int a,b;
int f[N];
int dep[N];
int vis[N];
int maxpos=0;
int maxsum=0x3f3f3f3f;
int n;
int res=0;
void dfs(int u,int fa)
{
	f[u]=1;int maxn=0;
	for(int i=0;i<G[u].size();i++)
	{
		int j=G[u][i];
		if(j==fa) continue;
		dfs(j,u);
		f[u]+=f[j];
		maxn=max(maxn,f[j]);
	}
	maxn=max(maxn,n-f[u]);
	if(maxn<maxsum||(maxn==maxsum&&(maxpos>u)))
	{
		maxsum=maxn;
		maxpos=u;
	}
}
void dfs2(int u,int fa,int cnt)
{
	dep[u]=cnt;
	for(int i=0;i<G[u].size();i++)
	{
		int j=G[u][i];
		if(j==fa) continue;
		 dfs2(j,u,cnt+1);
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n-1;i++) 
	{
		cin>>a>>b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	
	dfs(1,-1);
	queue<int> q;
	q.push(maxpos);
	dep[maxpos]=0;
	vis[maxpos]=1;
	while(q.size())
	{
		int t=q.front();
		q.pop();
		res=res+dep[t];
		for(int i=0;i<G[t].size();i++)
		{
			int j=G[t][i];
			if(j==t) continue;
			if(vis[j]==1) continue;
			dep[j]=dep[t]+1;
			vis[j]=1;
			q.push(j);
		}
	}
/*	dfs2(maxpos,maxpos,0);
	for(int i=1;i<=n;i++)
	{
	//	cout<<dep[i]<<endl;
		res=res+(dep[i]-dep[maxpos]);
	}*/
	cout<<maxpos<<" "<<res<<endl;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章