洛谷 P1273 有线电视网(dp)

Posted 一入OI深似海

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P1273 有线电视网(dp)相关的知识,希望对你有一定的参考价值。

/*
想了半天没想出状态 自己还是太弱了 QAQ
题目问的是最多供给多少户 一般想法是把这个值定义为状态量
没想出来QAQ....看了看题解的状态 很机智.... 
f[i][j]表示i的子树 选了j个叶子的最大收益
这样 不亏本就是收益>=0 
转移的话 先搜一下这个子树有几个叶子 然后枚举儿子 
枚举当前儿子分几个叶子 这里的枚举顺序有套路
从大到小枚举i分几个 从小到大枚举j分几个
这样可以避免 重复选择 
注意初始化 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 3010
using namespace std;
int n,m,p,head[maxn],num,f[maxn][maxn],ans,c[maxn];
struct node{
    int v,t,pre;
}e[maxn];
void Add(int from,int to,int dis){
    num++;e[num].v=to;
    e[num].t=dis;
    e[num].pre=head[from];
    head[from]=num; 
}
int Dfs(int u)
{
    if(u>p){
        f[u][1]=c[u];
        return 1;
    }
    int s=0;
    for(int i=head[u];i;i=e[i].pre){
        int v=e[i].v;
        int x=Dfs(v);s+=x;
        for(int j=s;j>=1;j--)
            for(int k=1;k<=x;k++)
                f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]-e[i].t);
    }
    return s;
}
int main()
{
    scanf("%d%d",&n,&m);p=n-m;
    for(int i=1;i<=p;i++){
        int x,y,z;
        scanf("%d",&x);
        for(int j=1;j<=x;j++){
            scanf("%d%d",&y,&z);
            Add(i,y,z);
        }
    }
    for(int i=p+1;i<=n;i++)
        scanf("%d",&c[i]);
    memset(f,-127/3,sizeof(f));
    for(int i=1;i<=n;i++)
        f[i][0]=0;
    Dfs(1);
    for(int i=0;i<=m;i++)
        if(f[1][i]>=0)ans=max(ans,i);
    printf("%d\n",ans);
    return 0;
} 

 

以上是关于洛谷 P1273 有线电视网(dp)的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1273 有线电视网

[P1273]有线电视网

luogu P1273 有线电视网 树上背包dp

[P1273] 有线电视网 (树形DP+分组背包)

luogu P1273 有线电视网

P1273 有线电视网