zoukankan      html  css  js  c++  java
  • poj 1947 树形背包 (删边)

    http://blog.csdn.net/woshi250hua/article/details/7632785

    这道题我一开始想的dp[i][j],i是节点,j是删除的点数,dp是最少删边的个数,然而状态转移方程不太好想。

    而题解其实差不多,只不过j为剩余点的个数

    这样我们就有最初状态,dp[i][1] = 子节点个数,而dp[i][j]就可以从子节点的状态推出来

    dp[i][j] = min(dp[i][j],dp[i][k]-1+dp[s][j-k])  (1<=i<=n,2<=j<=sum(节点总和),1<=k<j,s为i子节点)(i中已有k个节点并从s中选择j-k个,算最少删除边数,s选上所以i->s的边不需删除,所以-1)

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <cctype>
    #include <vector>
    #include <iterator>
    #include <set>
    #include <map>
    #include <sstream>
    using namespace std;
    
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pf printf
    #define sf scanf
    #define spf sprintf
    #define pb push_back
    #define debug printf("!
    ")
    #define MAXN 1010
    #define MAX(a,b) a>b?a:b
    #define blank pf("
    ")
    #define LL long long
    #define ALL(x) x.begin(),x.end()
    #define INS(x) inserter(x,x.begin())
    #define pqueue priority_queue
    #define INF 0x3f3f3f3f
    
    int n,m;
    
    struct node
    {
        int y,next;
    }tree[1050];
    
    int head[505],dp[505][505],ptr=1;
    
    int sum[505],vl[505],vis[505];
    
    
    void add(int x,int y)
    {
        tree[ptr].y = y;
        tree[ptr].next = head[x];
        head[x] = ptr++;
    }
    
    void dfs(int root)
    {
        if(vis[root]) return;
        int i,j,k;
        vis[root] = sum[root] = 1;
        int tot = 0;
    
        for(i=head[root]; i!=-1; i=tree[i].next)
        {
            int p = tree[i].y;
    
            if(!vis[p])
            {
                dfs(p);
                sum[root]+=sum[p];
                tot++;
                //pf("i%d p%d tot%d sum%d
    ",root,p,tot,sum[root]);
            }
        }
    
        dp[root][1] = tot;
    
        for(i=head[root]; i!=-1; i=tree[i].next)
        {
            int p = tree[i].y;
    
            for(j = sum[root];j>1;j--)
            {
                for(k = 1;k<j;k++)
                {
                    if(dp[root][k]!=INF && dp[p][j-k]!=INF)
                    {
                        dp[root][j] = min(dp[root][j],dp[root][k]+dp[p][j-k]-1);
                        //pf("i%d j%d k%d p%d dp%d
    ",root,j,k,p,dp[root][j]);
                    }
                }
            }
        }
    }
    
    int main()
    {
        int i,j,k,a,b;
        while(~sf("%d%d",&n,&m) && m+n>0)
        {
            mem(head,-1);
            ptr = 1;
    
            for(i=1;i<=n-1;i++)
            {
                sf("%d%d",&a,&b);
                add(a,b);
                add(b,a);
            }
    
            mem(dp,INF);
            mem(vis,0);
            dfs(1);
            int ans = INF;
            for (i = 1; i <= n; ++i) {
    
                if (i == 1)
                    ans = min(ans,dp[i][m]);
                else ans = min(ans,dp[i][m]+1);//非根节点要删除连到父亲节点的那条边
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    【POJ 2987 Firing】 最大权闭合子图
    【sgu176】有源汇有上下界的最大/最小流
    【HDU1263 水果】 STL之map应用经典好题
    【HDU1227 Fast Food】经典DP
    【hdu1043 && poj 1077】八数码问题
    有上下界的网络流问题
    【HDU4521】 dp思想+线段树操作
    miracl库下椭圆曲线方程常用函数使用入门
    函数指针
    python数据查询操作之 一场缺少db.commit()引发的血案……
  • 原文地址:https://www.cnblogs.com/qlky/p/5652067.html
Copyright © 2011-2022 走看看