poj 1947 树形dp

思路:dp[i][j]表示,以i节点为根,删去j个节点最少要断几条边。

那么dp[u][j]=min(dp[u][j],dp[v][k]+dp[u][j-k]);//选取最优状态

dp[u][j]=min(dp[u][j],dp[u][j-son[v]]+1);//切断与子节点相连的边

对于子节点

dp[v][n-son[v]]=1;

dp[v][j]=min(dp[v][j],dp[v][j-n+son[v]]+1)//表示不需要由父节点过来的那条分支

最有从所有状态中选举最优的dp[i][n-p];

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Maxn 160
#define Maxm 200010
#define LL __int64
#define Abs(x) ((x)>0?(x):(-x))
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
#define inf 0x7fffffff
#define Mod 1000000007
using namespace std;
int head[Maxn],vi[Maxn],e,dp[160][160],n,p,son[160],root[Maxn];
struct Edge{
    int u,v,next;
}edge[Maxm];
void init()
{
    memset(head,-1,sizeof(head));
    memset(vi,0,sizeof(vi));
    memset(son,0,sizeof(son));
    for(int i=1;i<=155;i++){
        root[i]=i;
        for(int j=1;j<=155;j++){
            dp[i][j]=200;
        }
        dp[i][0]=0;
    }
    e=0;
}
void add(int u,int v)
{
    edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++;
    edge[e].u=v,edge[e].v=u,edge[e].next=head[v],head[v]=e++;
}
void dfs(int u)
{
    int i,v,j,k;
    vi[u]=1;
    son[u]=1;
    for(i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].v;
        if(vi[v]) continue;
        dfs(v);
        son[u]+=son[v];
        for(j=n-1;j>=1;j--){
            for(k=1;k<=j;k++){
                dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v][k]);
            }
            if(j>=son[v])
            dp[u][j]=min(dp[u][j],dp[u][j-son[v]]+1);
        }
        dp[v][n-son[v]]=1;
        for(j=n-1;j>=n-son[v];j--)
        dp[v][j]=min(dp[v][j],dp[v][j-n+son[v]]+1);
    }
}
int main()
{
    int i,j,u,v;
    while(scanf("%d%d",&n,&p)!=EOF){
        init();
        for(i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        if(p==n){
            printf("0\n");
            continue;
        }
        if(p==n-1)
        {
            printf("1\n");
            continue;
        }
        dfs(1);
        int ans=200;
        for(i=1;i<=n;i++){
            ans=min(ans,dp[i][n-p]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2013-09-01 19:50  fangguo  阅读(143)  评论(0编辑  收藏  举报