zoukankan      html  css  js  c++  java
  • ural1018(树形dp)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17662

    题意:给一棵边有权值的二叉树,节点编号为1~n,1是根节点。求砍掉一些边,只保留q条边,这q条边构成的子树的根节点要求是1,求这颗子树的最大权值。

    分析:1.dp[u][i]表示已以u为根节点的子树,保留了i个节点的最大权值。每条边的权值,把它看作是连接的两个节点中的儿子节点的权值。那么总共要保留m+1个节点。

    所以有:dp[u][i]=max(dp[u][i],dp[v][k]+dp[u][i-k]+w).ans=dp[1][m+1].

            2.dp[u][i]表示u为根节点的子树,保留了i个条边的最大权值。在以u点为根节点的子树中选择了k条边,那么u的儿子节点v代表的子树中至多选k-1条边,因为如果在v子树中选边,那么u到v的边必选。

    所以有:dp[u][i]=max(dp[u][i],dp[u][i-k]+dp[v][k-1]+w).ans=dp[1][m].

    方法1的代码:

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cstdlib>
    #include <stack>
    #include <vector>
    #include <set>
    #include <map>
    #define LL long long
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define N 110
    #define clr(a) (memset(a,0,sizeof(a)))
    using namespace std;
    struct edge
    {
        int v,w,next;
        edge(){}
        edge(int v,int w,int next):v(v),w(w),next(next){}
    }e[2*N];
    int head[N],dp[N][N],num[N],tot,n,m;
    void addedge(int u,int v,int w)
    {
        e[tot]=edge(v,w,head[u]);
        head[u]=tot++;
    }
    void dfs(int u,int fa)
    {
        num[u]=1;
        for(int i=head[u];~i;i=e[i].next)
        {
            int v=e[i].v,w=e[i].w;
            if(v==fa)continue;
            dfs(v,u);
            num[u]+=num[v];
            for(int j=num[u];j>=1;j--)
                for(int k=1;k<j&&k<=num[v];k++)//注意这里k<j.因为子树根节点u点必选,在子树节点中至多选j-1个
                    dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]+w);
        }
    }
    int main()
    {
        int u,v,w;
        while(scanf("%d%d",&n,&m)>0)
        {
            memset(head,-1,sizeof(head));
            clr(dp);tot=0;
            for(int i=1;i<n;i++)
            {
                scanf("%d%d%d",&u,&v,&w);
                addedge(u,v,w);
                addedge(v,u,w);
            }
            dfs(1,-1);
            printf("%d
    ",dp[1][m+1]);
        }
    }
    View Code

    方法2的代码:

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cstdlib>
    #include <stack>
    #include <vector>
    #include <set>
    #include <map>
    #define LL long long
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define N 110
    #define clr(a) (memset(a,0,sizeof(a)))
    using namespace std;
    struct edge
    {
        int v,w,next;
        edge(){}
        edge(int v,int w,int next):v(v),w(w),next(next){}
    }e[2*N];
    int head[N],dp[N][N],tot,n,m;
    void addedge(int u,int v,int w)
    {
        e[tot]=edge(v,w,head[u]);
        head[u]=tot++;
    }
    void dfs(int u,int fa)
    {
        for(int i=head[u];~i;i=e[i].next)
        {
            int v=e[i].v,w=e[i].w;
            if(v==fa)continue;
            dfs(v,u);
            for(int j=m;j>=1;j--)
                for(int k=1;k<=j;k++)
                    dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k-1]+w);
        }
    }
    int main()
    {
        int u,v,w;
        while(scanf("%d%d",&n,&m)>0)
        {
            memset(head,-1,sizeof(head));
            clr(dp);tot=0;
            for(int i=1;i<n;i++)
            {
                scanf("%d%d%d",&u,&v,&w);
                addedge(u,v,w);
                addedge(v,u,w);
            }
            dfs(1,-1);
            printf("%d
    ",dp[1][m]);
        }
    }
    View Code
  • 相关阅读:
    IOS tableView的数据刷新
    IOS Modal(切换另外控件器方式)
    IOS UITabBarController(控制器)的子控制器
    iOS 应用数据存储的常用方式
    IOS 获取文本焦点 主动召唤出键盘(becomeFirstResponder) and 失去焦点(退下键盘)
    集合类型
    提取URL的搜索字符串中的参数
    本地对象、内置对象、宿主对象
    声明函数 执行上下文 匿名函数
    完善tab页面定位
  • 原文地址:https://www.cnblogs.com/lienus/p/4202354.html
Copyright © 2011-2022 走看看