求树的重心。树的重心是指去掉重心之后剩下的子树的最大结点个数最少
树形DP,dp[i]表示以i为重心,剩下的子树的最大结点个数,状态转移dp[i] = max(dp[i], siz[j])。
注意用vector超时。
树形DP,dp[i]表示以i为重心,剩下的子树的最大结点个数,状态转移dp[i] = max(dp[i], siz[j])。
注意用vector超时。
代码如下:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<cstring>
#include<string>
#include<vector>
#define N 50005
#define inf 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 10e-6
using namespace std;
int n,tot;
int siz[N],dp[N],head[N];
struct node
{
int next,v,w;//next邻接表中的下一条边的编号,v边所到达的点,w权值
}edge[N*2];
void addedge(int u,int v)
{
edge[tot].next = head[u];
edge[tot].v = v;
head[u] = tot++;
}
void dfs(int u,int pa)
{
siz[u] = 1;
dp[u] = 0;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
if(v == pa) continue;
dfs(v,u);
siz[u] += siz[v];
dp[u] = max(siz[v],dp[u]);
}
dp[u] = max(dp[u], n-siz[u]);
}
int main()
{
while(scanf("%d",&n) != EOF)
{
int i;
memset(siz,0,sizeof(siz));
memset(head,-1,sizeof(head));
for(i = 1; i < n; i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
tot = 0;
dfs(1,0);
int ans = inf;
for(i = 1; i <= n; i++) ans = min(ans,dp[i]);
for(i = 1; i <= n; i++) if(ans == dp[i]) { printf("%d",i); break;}
for(i = i+1; i <= n; i++) if(ans == dp[i]) printf(" %d",i);
printf("\n");
}
return 0;
}