1. 程式人生 > >luogu P1273 有線電視網

luogu P1273 有線電視網

size clu read pac Go 需求 urn std p12

題目鏈接

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

luogu P1273 有線電視網