POJ-3107 Godfather
题目大意:给一棵无根树,找出所有满足下面的条件的点:删除它后,最大子树中的个数最少。
题目分析:两次深搜,第一次找出子树中节点的个数,第二次维护最大子树。
ps:边用vector保存时会超时。。。
代码如下:
# include<iostream> # include<cstdio> # include<cstring> # include<vector> # include<queue> # include<list> # include<set> # include<map> # include<string> # include<cmath> # include<cstdlib> # include<algorithm> using namespace std; # define LL long long const int N=1005; const int INF=1000000000; struct Edge { int to,nxt; }; int n,cnt=0; int d[N*50]; int dp[N*50]; int head[N*50]; Edge e[N*100]; void add(int u,int v) { e[cnt].to=v; e[cnt].nxt=head[u]; head[u]=cnt++; } void init() { int a,b; cnt=0; memset(head,-1,sizeof(head)); for(int i=1;i<n;++i){ scanf("%d%d",&a,&b); add(a,b); add(b,a); } } void dfs(int u,int fa) { d[u]=1; for(int i=head[u];i!=-1;i=e[i].nxt){ int v=e[i].to; if(v==fa) continue; dfs(v,u); d[u]+=d[v]; } } void dfs1(int u,int fa) { dp[u]=n-d[u]; for(int i=head[u];i!=-1;i=e[i].nxt){ int v=e[i].to; if(v==fa) continue; dfs1(v,u); if(dp[u]<d[v]) dp[u]=d[v]; } } void solve() { dfs(1,-1); dfs1(1,-1); int minn=INF; for(int i=1;i<=n;++i) minn=min(minn,dp[i]); int flag=false; for(int i=1;i<=n;++i){ if(dp[i]!=minn) continue; if(flag) printf(" "); printf("%d",i); flag=true; } printf("\n"); } int main() { while(~scanf("%d",&n)) { init(); solve(); } return 0; }