問題 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;
}

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