luogu P1273 有线电视网 树上背包dp
Posted qingyuyyyyy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P1273 有线电视网 树上背包dp相关的知识,希望对你有一定的参考价值。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 3030;
int h[N], e[N], ne[N], w[N], idx;
int val[N];
int n, m;//n为整个有线电视网的结点总数,m为用户终端的数量
int dp[N][N];//dp[i][j]表示i节点,选j个用户,能得到的钱的最大值
void add(int a, int b, int c)
{
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
int dfs(int u)
{
if(u > n - m)//u为用户终端
{
dp[u][1] = val[u];
return 1;
}
int sum = 0;
for(int k = h[u]; k !=-1; k = ne[k])
{
int v = e[k];
int t = dfs(v);
sum += t;
for(int j = sum; j > 0; j --)
for(int i = 1; i <= t; i ++)
if(j - i >= 0)//因为是从下往上递归,所以之前的边都减过了,减去当前的边
dp[u][j] = max(dp[u][j], dp[u][j - i] + dp[v][i] - w[k]);
}
return sum;
}
int main()
{
memset(dp,~0x3f,sizeof(dp));
memset(h, -1, sizeof h);
cin >> n >> m;
for(int u = 1; u <= n - m; u ++)
{
int size;
cin >> size;
for(int j = 1; j <= size; j ++)
{
int b, c;
cin >> b >> c;
add(u, b, c);
}
}
for(int i = n - m + 1; i <= n; i ++)
cin >> val[i];
for(int i = 1; i <= n; i ++)
dp[i][0] = 0;//选0个用户的花费肯定是0啦
dfs(1);
for(int i = m; i >= 1; i --)
if(dp[1][i] >= 0)
{
cout << i << endl;
break;
}
return 0;
}
以上是关于luogu P1273 有线电视网 树上背包dp的主要内容,如果未能解决你的问题,请参考以下文章