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

题意:给出一棵树,有边权,只有叶子节点有点权,求一个合法方案(选择走到哪几个叶子节点,且路径上的权值和 <= 要走到的叶子节点的点权和),使得选择的叶子节点数量尽量的多;

解法:树形DP+分组背包;

1.树形DP;这是一棵树,所以叫树形DP;

2.分组背包;在这里主要是运用到了它的思想;我们可以设 f[i][j],表示 i节点选择了 j个叶子节点的费用最大值;假设现在在 x节点,它的下面有 n个叶子节点(不是它的儿子),那么我们就要处理出它选 1,2,3,……,n 个叶子节点的情况,但是由于这是一棵树,所以 x节点的状态又要由它的儿子节点转移过来,而它的儿子节点又包含有叶子节点……

这不是很像是分组背包吗,我们只要将 x节点的每一个儿子看作是将要放进 x这个背包的的物品组别,而 x节点的儿子的叶子节点数量就是这个物品组别的物品数量,每次从 x节点的一棵子树递归回来,我们就可以进行一次 DP,每一次 DP就像是在这个这个儿子(组别)上进行一次分组背包操作,当递归完后,就可以得出答案啦;

附上代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 3e3+10;
const int inf = 0x3f3f3f3f;

int n,m;
int val[N];
struct edge{
    int next,to,w;
}a[N<<4];
int head[N],cnt;
int fa[N],size[N];
int f[N][N],vis[N];

void add(int u,int v,int w){
    a[++cnt]=(edge){head[u],v,w};
    head[u]=cnt;
}

int dfs(int x){
    if(val[x]){
        f[x][1]=val[x];
        return 1;
    }
    int sum=0,t;
    for(int i=head[x];i;i=a[i].next){
        int v=a[i].to;
        t=dfs(v);
        sum+=t;
        for(int j=sum;j>=1;--j)
        for(int k=1;k<=t;++k) f[x][j]=max(f[x][j],f[x][j-k]+f[v][k]-a[i].w);
    }
    return sum;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,k;i<=n-m;++i){
        scanf("%d",&k);
        for(int j=1,x,y;j<=k;++j){
            scanf("%d%d",&x,&y);
            add(i,x,y);
        }
    }
    for(int i=n-m+1;i<=n;++i) scanf("%d",&val[i]);
    memset(f,-inf,sizeof(f));
    for(int i=1;i<=n;++i) f[i][0]=0;
    dfs(1);
    for(int i=m;i>=1;--i){
        if(f[1][i]>=0){
            printf("%d",i);
            break;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/nnezgy/p/11579277.html

时间: 2024-12-27 18:13:03

[P1273] 有线电视网 (树形DP+分组背包)的相关文章

Luogu P1273 有线电视网(树形dp+背包)

题面 题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从转播站到转播站以及从转播站到所有用户终端的信号传输费用都是已知的,一场转播的总费用等于传输信号的费用总和. 现在每个用户都准备了一笔费用想观看这场精彩的足球比赛,有线电视网有权决定给哪些用户提供信号而不给哪些用户提供信号. 写一个程序找出一个方案使得有线电视网在不亏本的情况下使观看转播的用户尽可能多. 输入输出格

hdu4003 树形dp+分组背包

http://acm.hdu.edu.cn/showproblem.php?pid=4003 Problem Description Humans have discovered a kind of new metal mineral on Mars which are distributed in point‐like with paths connecting each of them which formed a tree. Now Humans launches k robots on

HDU ACM 4044 GeoDefense -&gt;树形DP+分组背包

题意:地图是一个编号为1-n的节点的树,节点1是敌方基地,其他叶节点是我方基地.敌人基地会出来敌人,为了防止敌人攻进我方基地,我们可以选择造塔.每个节点只能造一个塔,节点i有ki种塔供选择,价值和攻击力为price_i, power_i,攻击力power_i是让敌人经过这个节点时让敌人的HP减少power_i点.因此从敌人基地到我方任意一个基地的路径,这条路径上所有塔的攻击力之和,就是这个基地的抵抗力. 敌人攻击路径不确定,为了保护我方所有基地,需要确定所有基地中抵抗力最低的一个.我方只有数量为

POJ 2486 Apple Tree 树形DP+分组背包

链接:http://poj.org/problem?id=2486 题意:一棵(苹果)树,树上有N个结点(N<=100),起点是结点1.每个结点上有若干个苹果,我可以进行K步操作(K<=200),每次操作是从当前结点移动到相邻的结点,并且到了相邻的结点以后会吃掉上面的所有苹果并且苹果不再长出来,相邻是指两个结点之间有边相连.问在K步操作之后最多可以吃掉多少个苹果. 思路:刚入手的时候觉得是一般的树形背包问题,dp[i][j]代表的是以i为根的子树中走j个结点所能吃到的苹果数,来进行状态转移,但

hdu4044 树形dp+分组背包

http://acm.hdu.edu.cn/showproblem.php?pid=4044 Problem Description Tower defense is a kind of real-time strategy computer games. The goal of tower defense games is to try to stop enemies from reaching your bases by building towers which shoot at them

HDU-1011 Starship Troopers (树形DP+分组背包)

题目大意:给一棵有根带点权树,并且给出容量.求在不超过容量下的最大权值.前提是选完父节点才能选子节点. 题目分析:树上的分组背包. ps:特判m为0时的情况. 代码如下: # include<iostream> # include<cstdio> # include<vector> # include<cstring> # include<algorithm> using namespace std; const int N=105; const

luoguP1273 有线电视网 [树形dp]

题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从转播站到转播站以及从转播站到所有用户终端的信号传输费用都是已知的,一场转播的总费用等于传输信号的费用总和. 现在每个用户都准备了一笔费用想观看这场精彩的足球比赛,有线电视网有权决定给哪些用户提供信号而不给哪些用户提供信号. 写一个程序找出一个方案使得有线电视网在不亏本的情况下使观看转播的用户尽可能多. 输入输出格式 输

hdu 1561 树形dp+分组背包

题意:就是给定n个点,每个地点有value[i]的宝物,而且有的宝物必须是另一个宝物取了才能取,问取m个点可以获得的最多宝物价值. 一个子节点就可以返回m个状态,每个状态表示容量为j(j<=m)时选最多的宝物,而一个子节点中只可以选择一个状态进行转移,每个节点有若干个子节点,问题就转换为分组背包,几个子节点就是几个分组背包,体积是选几个地点,价值是宝物价值. 状态转移方程: dp[v][1] = Money[v]; (v为叶子节点)                    dp[v][j] = m

【P2015】二叉苹果树 (树形DP分组背包)

题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果. 给定需要保留的树枝数量,求出最多能留住多少苹果. 输入输出格式 输入格式: 第1行2个数,N和Q(1<=Q<= N,1<N<=100). N表示树的结点数,Q表示要保留的树枝数量.接下来N-1行描述树枝的信息. 每行3个整数,前两个是它连接的结点的编号.第3个数是