zoukankan      html  css  js  c++  java
  • 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
    ");
                continue;
            }
            if(p==n-1)
            {
                printf("1
    ");
                continue;
            }
            dfs(1);
            int ans=200;
            for(i=1;i<=n;i++){
                ans=min(ans,dp[i][n-p]);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Icident event 分析
    innodb buffer pool相关特性
    备库Seconds_Behind_Master的计算
    savepoint原理
    layer探框
    解决layui表格和下拉框同时使用时,下拉框被表格遮当问题
    layui switch开关按钮
    formSelects 4.x多选下拉框
    java如何调用php接口,并获取值
    layui时间范围选择器
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3295190.html
Copyright © 2011-2022 走看看