題目描述
有一個村莊居住着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;
}