zoukankan      html  css  js  c++  java
  • luoguP2015(简单树形DP)

    题目链接:https://www.luogu.org/problemnew/show/P2015

    题意:给定一颗结点个数为n的树,有n-1条边,每条边有个权值,树根为1。现在给出q <=n,问剪枝后保留q条边后的边的权值最大是多少。

    思路:首先要知道这道题有个隐含条件,如果某条边被保留,那么从根节点到这个点路径上的所有点都必须保留。

       我们用dp[i][j]表示顶点i的子树上保留j条边的最大权值和是多少。

       给出状态转移方程:dp[x][j]=max(dp[x][j] , dp[x][j-1-k]+dp[y][k]+edge[i].w)

       其中x是当前结点,y是x的一个子结点,k表示结点y上保留的边数,0<j<=min(siz[x],q),0=<k<=min(siz[y],j-1)。因为要把x和y之间的边算上,所以是j-1-k。

       其中j需要倒序枚举,类似01背包。

    AC代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int maxn=105;
    
    struct node{
        int v,w,nex;
    }edge[maxn<<1];
    
    int n,q,cnt,head[maxn],siz[maxn];
    int dp[maxn][maxn];
    
    void adde(int u,int v,int w){
        edge[++cnt].v=v;
        edge[cnt].w=w;
        edge[cnt].nex=head[u];
        head[u]=cnt;
    }
    
    void dfs(int x,int f){
        for(int i=head[x];i;i=edge[i].nex){
            int y=edge[i].v;
            if(y==f) continue;
            dfs(y,x);
            siz[x]+=siz[y]+1;
            for(int j=min(siz[x],q);j;--j)
                for(int k=0;k<=min(siz[y],j-1);++k)
                    dp[x][j]=max(dp[x][j],dp[x][j-1-k]+dp[y][k]+edge[i].w);
        }
    }
    
    int main(){
        scanf("%d%d",&n,&q);
        for(int i=1;i<n;++i){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            adde(u,v,w);
            adde(v,u,w);
        }
        dfs(1,-1);
        printf("%d
    ",dp[1][q]);
        return 0;
    }
  • 相关阅读:
    jQuery 2.0.3 源码分析 Deferred(最细的实现剖析,带图)
    jQuery 2.0.3 源码分析 Deferrred概念
    jQuery 2.0.3 源码分析core
    jQuery 2.0.3 源码分析core
    JavaScript异步机制
    使用Node.js实现数据推送
    自定义jQuery插件Step by Step
    转 CSS hack:针对IE6,IE7,firefox显示不同效果
    ie6,ie7兼容性总结(转)
    QQ浏览器X5内核问题汇总
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11185440.html
Copyright © 2011-2022 走看看