• 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
  • 相关阅读:
    openlayers6聚合图(附源码下载)
    arcgis api 4.x for js地图加载第三方矢量切片
    leaflet读取tif像素值的两种实现方式(附源码下载)
    openlayers6热力图(附源码下载)
    cesium 3dtiles模型单体化点击高亮效果
    leaflet聚合图功能(附源码下载)
    openlayers6绘制扇形(附源码下载)
    【 Windows 10】神州网信政府版官方镜像
    Windows10 解决“装了 .NET Framework 4.5.2/4.6.1/4.7.1等等任何版本 或版本更高的更新”问题
    App.config/Web.config 中特殊字符的处理
  • 原文地址:https://www.cnblogs.com/lienus/p/4202354.html
Copyright © 2020-2023  润新知