树形DP(Rebuilding Roads poj1947)

题意:给出一颗树,求要形成一颗元素个数是p的子树,最少要去掉多少边

#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"algorithm"
#define M 222
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
    int u,v,next;
}edge[M*2];
int t,head[M],dp[M][M],num[M],degree[M];
void init()
{
    t=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
    edge[t].u=u;
    edge[t].v=v;
    edge[t].next=head[u];
    head[u]=t++;
}
void dfs(int u,int f)//对于每个点的子树处理
{
    num[u]=1;
    dp[u][1]=degree[u];//对于每个点只取一个点
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==f)continue;
        dfs(v,u);
        num[u]+=num[v];
        for(int j=num[u];j>=1;j--)
        {
            for(int k=1;k+1<=j;k++)
            dp[u][j]=min(dp[u][j],dp[u][k]+dp[v][j-k]-2);
        }
    }
}
int main()
{
    int n,p,i;
    while(scanf("%d%d",&n,&p)!=-1)
    {
        init();
        memset(degree,0,sizeof(degree));
        for(i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
            degree[a]++;
            degree[b]++;
        }
        memset(dp,inf,sizeof(dp));
        dfs(1,1);
        int ans=inf;
        for(i=1;i<=n;i++)
        {
            if(ans>dp[i][p])
                ans=dp[i][p];
        }
        printf("%d
",ans);
    }
}


原文地址:https://www.cnblogs.com/mypsq/p/4348103.html