[P1273] cable television network (tree backpack packet DP +)

Meaning of the questions: Given a tree, the right side there is only a little right leaf nodes, find a legitimate program (select where are several leaf nodes, and point values ​​on the right path and <= to come to the leaf node and as much as possible the number of rights), such that the selected leaf node;

Solution: DP + tree packet backpack;

1. the DP tree; it is a tree, the tree is called the DP;

2. Group backpack; here is mainly applied to its ideology; we can set f [i] [j], i represents the selected node j leaf nodes of the maximum costs; Suppose now that node in x, it's below n leaf nodes (not its son), then we will deal with it the election 1,2,3, ......, n the case of a leaf node, but since this is a tree, the nodes but also state x by its son transferred from the node, and its son nodes and leaf nodes contain ......

This is not like a backpack groups do, as long as we each node x son considered this to be put in the backpack x group of items, while the number of leaf nodes node is the son of x number of items in this article groups each recursive subtree from node x to come back, we will be able to conduct a DP, DP is like every once in this grouping backpack operating on the son (group), when a recursive finished, can be drawn The answer it;

Attach Code:

#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;
}

 

Guess you like

Origin www.cnblogs.com/nnezgy/p/11579277.html