poj 3107 树型DP

来源:互联网 发布:淘宝可以关注的人 编辑:程序博客网 时间:2024/05/19 22:06

题意:

一个无向树,去掉某一个节点,会出现几个连通块,问去掉哪些个节点,会使剩下的连通块中  含有最多节点个数的那个连通块节点个数最小。

题解:sum数组存储子树的节点个数,max1数组存储孩子树中节点最大值。最大的连通块值就是max(max1[i],n-sum[i]);


这道题靠自己1A了,所以今天上午好开心啊~~

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int sum[50010],max1[50010],list[50010],n,pos;struct P{int u,v,next;}point[100010];struct It{int numb,ki;}it[50010];void add(int son,int fa){point[pos].u=fa;point[pos].v=son;point[pos].next=list[fa];list[fa]=pos++;}void dfs(int son,int fa){int now=list[son];sum[son]=1;while(now!=-1){if(point[now].v==fa){now=point[now].next;continue;}dfs(point[now].v,son);sum[son]+=sum[point[now].v];max1[son]=max(max1[son],sum[point[now].v]);now=point[now].next;}return;}void dfs1(int son,int fa){if(fa==0){it[son].ki=max1[son];}else{it[son].ki=max(max1[son],n-sum[son]);}int now=list[son];while(now!=-1){if(point[now].v==fa){now=point[now].next;continue;}dfs1(point[now].v,son);now=point[now].next;}return;}int cmp(It a,It b){if(a.ki<b.ki){return a.ki<b.ki;}else if(a.ki==b.ki){return a.numb<b.numb;}elsereturn a.ki<b.ki;}int main(){while(scanf("%d",&n)!=EOF){pos=0;memset(list,-1,sizeof(list));for(int i=1;i<n;i++){int a,b;scanf("%d%d",&a,&b);add(a,b);add(b,a);it[i].numb=i;}it[n].numb=n;memset(sum,0,sizeof(sum));memset(max1,0,sizeof(max1));dfs(1,0);dfs1(1,0);//for(int i=1;i<=n;i++){//printf("! sum=%d max1=%d ki=%d\n",sum[i],max1[i],it[i].ki);//}sort(it+1,it+n+1,cmp);int k=it[1].ki;printf("%d",it[1].numb);for(int i=2;i<=n&&it[i].ki==k;i++){printf(" %d",it[i].numb);}printf("\n");}return 0;}



原创粉丝点击