题目描述
有一个村庄居住着n个村民,有n-1条路径使得这n个村民的家联通,每条路径的长度都为1。现在村长希望在某个村民家中召开一场会议,村长希望所有村民到会议地点的距离之和最小,那么村长应该要把会议地点设置在哪个村民的家中,并且这个距离总和最小是多少?若有多个节点都满足条件,则选择节点编号最小的那个点。
输入输出格式
输入格式:
第一行。一个数n,表示有n个村民。
接下来n-1行,每行两个数字a和b,表示村民a的家和村民b的家之间存在一条路径。
输出格式:
一行输出两个数字x和y
x表示村长将会在哪个村民家中举办会议
y表示距离之和的最小值
输入输出样例
输入样例#1:
4 1 2 2 3 3 4
输出样例#1:
2 4
说明
【数据范围】
70%数据n<=1000
100%数据n<=50000
找树的重心,dfs
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> using namespace std; const int N = 50002; int n; int num; int head[50002]; struct node{ int v,next,w; }edge[50001*2]; int son[N],siz;bool vis[N];int ans=0; void add_edge(int x,int y) { edge[++num].v=y;edge[num].w=1;edge[num].next=head[x];head[x]=num; } void dfs(int x) { vis[x]=1; son[x]=0; int tmp=0; for(int i=head[x];i;i=edge[i].next) { int v=edge[i].v; if(!vis[v]) { dfs(v); son[x]+=son[v]+1; tmp=max(tmp,son[v]+1); } } tmp=max(tmp,n-son[x]-1); if(siz>tmp||tmp==siz&&ans>x) { ans=x; siz=tmp; } } int aans;int dep[N]; void dfs2(int x,int fa,int step) { dep[x]=step; for(int i=head[x];i;i=edge[i].next) { int v=edge[i].v; if(v==fa)continue; dfs2(v,x,step+1); } } int main() { scanf("%d",&n);int u,v; for(int i=1;i<=n-1;i++) { scanf("%d%d",&u,&v);add_edge(u,v);add_edge(v,u); } siz=0x7fffffff; dfs(1); dfs2(ans,ans,0); for(int i=1;i<=n;i++) aans+=abs(dep[ans]-dep[i]); printf("%d %d",ans,aans); return 0; }