POJ 1947树形DP

来源:互联网 发布:弱矩阵 编辑:程序博客网 时间:2024/05/18 02:11

题目:

给你一棵树,求最少剪掉几条边使能够得到一个p个节点的树。

解题思路:

dp[i][j]代表以i为根的子树要变成j个节点需要剪掉的边数

d[i][j] = max(dp[i][j], dp[i][k]+dp[son][j-k]);

注意最后的选择中,非根节点的要加上减去连接父节点的那条边。

// Poj 1947 Rebuilding Roads //////题目大意:给定一棵节点数为n的树,问从这棵树最少删除几条边使得某棵子树的节点个数为p,1<=n<=150,1<=p<=n。//////是二维。。。//所谓分组背包的部分在哪里。。?!!!!//过鸟。。。#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string.h>#include<algorithm>#define inf 0x3fffffff#define maxn 300#define maxm 300using namespace std;int n;int em;int head[maxn];int dp[maxn][maxn],du[maxn];int sum[maxn],chu[maxn];void init(){    em=0;    memset(head,-1,sizeof(head));     for(int i=0;i<=n;i++)        for(int j=0;j<=n;j++)        dp[i][j]=inf;    memset(du,0,sizeof(du));    memset(chu,0,sizeof(chu));}struct node{    int u,v,next;}edge[maxm];void addedge(int u,int v){    edge[em].u=u;edge[em].v=v;    edge[em].next=head[u];    head[u]=em++;}void tree_dp(int u,int fa){//    cout<<u<<" "<<fa<<endl;    sum[u]=1;    for(int i=head[u];~i;i=edge[i].next)    {        int v=edge[i].v;        if(v==fa) continue;        tree_dp(v,u);        sum[u]+=sum[v];    }    dp[u][sum[u]]=0;    dp[u][1]=chu[u];    for(int i=head[u];~i;i=edge[i].next)    {        int v=edge[i].v;        if(v==fa) continue;        for(int j=sum[u];j>=2;j--)            for(int k=1;k<=sum[v];k++)            if(j>=k &&(dp[u][j-k]!=inf) &&(dp[v][k]!=inf))        dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v][k]-1);//cout<<u<<" "<<j<<" u,j "<<dp[u][j]<<" "<<u<<" "<<j-k<<" u,j-k "<<dp[u][j-k]<<" "<<v<<" "<<k<<" v,k  "<<dp[v][k]<<endl;    }}int main(){    int p,a,b;//    freopen("112.txt","r",stdin);    while(scanf("%d%d",&n,&p)!=EOF)    {         init();        for(int i=1;i<=n-1;i++)            scanf("%d%d",&a,&b),addedge(a,b),du[b]++,chu[a]++;       int root;       for(int i=1;i<=n;i++)         if(du[i]==0) root=i;        tree_dp(root,0);    int mi=inf;    for(int i=1;i<=n;i++)    {        if(i==root) mi=min(dp[i][p],mi);        else mi=min(dp[i][p]+1,mi);    }//如果不是根节点要要删除连接父亲的边。    printf("%d\n",mi);    }    return 0;}

0 0
原创粉丝点击