luogu P1273 有线电视网

题目链接

luogu P1273 有线电视网

题解

树形背包
dp[i][j]表示在以i为根的子树中,满足j个客户的需求所能获得的最大收益

代码

#include<cstdio>
#include<algorithm>
#include<cstring>
const int maxn = 3007;

//using namespace std;
inline int read() {
    int x = 0,f = 1;
    char c = getchar();
    while(c < '0' || c > '9'){ if(c == '-') f = -1; c = getchar(); }
    while(c <= '9' && c >= '0') x = x * 10 + c - '0', c = getchar();
    return x * f; 
}
int n , m;
struct Node {
    int v , w, next;			
}edge[maxn << 1];
int num , head[maxn];
inline void add_edge(int u,int v,int w) {edge[++ num].v = v,edge[num].w = w;edge[num].next = head[u];head[u] = num; }
int cost[maxn],son[maxn];
int dp[maxn][maxn];
void dfs(int u,int fa) { 
    dp[u][0] = 0;
    if(u >= n - m + 1) {
        dp[u][1] = cost[u]; 
        son[u] = 1; return;	
    }
    for(int num = 0,i = head[u]; i ;i = edge[i].next) {
        int v = edge[i].v;
        if(v == fa) continue;
        dfs(v,u); 
        son[u] += son[v];
        for(int j = son[u];j >= 1; --j)
            for(int k = 0;k <= std::min(son[v],j);++ k) 
                dp[u][j] = std::max(dp[u][j],dp[u][j - k] + dp[v][k] - edge[i].w);
    }
}
int main() {
    memset(dp,-0x3f,sizeof dp);
    //printf("%d\n",dp[1][0]);
    n = read(),m = read();
    for(int k,i = 1;i <= n - m;++ i) {
        k = read();
        for(int v,w,j = 1;j <= k;++ j) {
            v = read(),w = read();
            add_edge(i,v,w);
            add_edge(v,i,w);
        }
    }
    for(int i = n - m + 1;i <= n; ++i ) cost[i] = read();
    dfs(1,1);
    for(int i = m;i >= 0; -- i) if(dp[1][i] >= 0)  { printf("%d\n",i);break; }
    return 0;
}		
posted @ 2018-04-17 21:04  zzzzx  阅读(131)  评论(1编辑  收藏  举报