题目地址:POJ 3107
树形DP水题。记录下每个点的子树的最多节点数,以及所有子树的总结点数。然后遍历找就行了。
代码如下:
#include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h> using namespace std; #define LL __int64 #define pi acos(-1.0) const int mod=100000000; const int INF=0x3f3f3f3f; const double eqs=1e-8; int dp[60000], head[60000], cnt, tot[60000], c[60000], num, min1; struct node { int u, v, next; } edge[120000]; void add(int u, int v) { edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } void dfs(int u, int fa) { tot[u]=1; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(v==fa) continue ; dfs(v,u); dp[u]=max(dp[u],tot[v]); tot[u]+=tot[v]; } } void init() { memset(head,-1,sizeof(head)); memset(dp,0,sizeof(dp)); cnt=0; num=0; min1=INF; } int main() { int n, i, j, u, v; while(scanf("%d",&n)!=EOF) { init(); for(i=1; i<n; i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs(1,-1); for(i=1; i<=n; i++) { dp[i]=max(dp[i],n-tot[i]); if(min1>dp[i]) { min1=dp[i]; } } for(i=1; i<=n; i++) { if(dp[i]==min1) { c[num++]=i; } } for(i=0; i<num; i++) { printf("%d",c[i]); if(i!=num-1) printf(" "); } puts(""); } return 0; }
原文地址:http://blog.csdn.net/scf0920/article/details/42834595