Codeforce 581F(树形dp)

来源:互联网 发布:元数据驱动 force.com 编辑:程序博客网 时间:2024/06/07 17:36

链接:点击打开链接

题意:给出一个树,要求最少删除多少条边使叶子节点恰好平分

代码:

#include <vector>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <iostream>#include <algorithm>using namespace std;const int INF=0x3f3f3f3f;int n,p;int dp[5005][5005],num[5005],used[5005];        //dp[i][j]为以i为根节点的子树将j个节点分出vector<int> G[5005];                           //去删除的边的数目void dfs1(int s){    int i,tmp,sum;    sum=0;    used[s]=1;    num[s]=(G[s].size()==1);    for(i=0;i<G[s].size();i++){        tmp=G[s][i];        if(G[tmp].size()&&!used[tmp]){            sum++;            dfs1(tmp);            num[s]+=num[tmp];        }    }                                           //叶子节点数//    dp[s][1]=sum;}void dfs2(int s){    int i,j,k,tmp;    used[s]=1;    for(i=0;i<G[s].size();i++){        tmp=G[s][i];        if(!used[tmp]){            dfs2(tmp);            for(j=num[s];j>=0;j--)            for(k=0;k<=min(j,num[tmp]);k++)            dp[s][j]=min(dp[s][j],dp[s][j-k]+dp[tmp][k]);        }    }    for(i=0;i<=num[s];i++)                      //根据s的父节点推出        dp[s][num[s]-i]=min(dp[s][num[s]-i],dp[s][i]+1);}int main(){    int i,j,a,b,ans,root;    while(scanf("%d",&n)!=EOF){        memset(dp,INF,sizeof(dp));        memset(used,0,sizeof(used));        for(i=1;i<=n;i++)        G[i].clear();        for(i=1;i<n;i++){            scanf("%d%d",&a,&b);            G[a].push_back(b);            G[b].push_back(a);        }        if(n==2){                               //两个节点没有根节点,因此直接输出1            puts("1");            continue;        }        root=1;        while(G[root].size()==1)        root++;        dfs1(root);        for(i=1;i<=n;i++)        dp[i][0]=0;        memset(used,0,sizeof(used));        dfs2(root);        printf("%d\n",dp[root][num[root]/2]);    }    return 0;}


 

 

0 0
原创粉丝点击