题目大意:每个用户必须连一个发射器,发射的信号从一个点到另一个点需要费用,问电视台在不亏本的情况下最多可以给多少个用户发射信号。
思路:dp[i][j]表示节点i发射j个信号给用户的盈利。注意:dp数组初始化时,dp[i][0] = 0;其余的负无穷,否则会出bug。自己跟着程序走一遍思路会清晰很多。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 3005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 100000000
int n , id , m;
int res[maxn] , tmp[maxn];
struct edge
{
int u , v , w;
int next;
}E[maxn];
int head[maxn];
int dp[maxn][maxn];
int val[maxn];
void add(int u , int v , int w)
{
E[id].u = u;
E[id].v = v;
E[id].w = w;
E[id].next = head[u];
head[u] = id++;
}
void dfs(int root)
{
for(int i = head[root] ; i != -1 ; i = E[i].next)
{
dfs(E[i].v);
for(int j = 0 ; j <= res[root] ; j ++) tmp[j] = dp[root][j];
for(int j = 0 ; j <= res[root] ; j ++)
{
for(int k = 1 ; k <= res[E[i].v] ; k ++)
{
dp[root][j+k] = max(dp[root][j+k] , tmp[j] + dp[E[i].v][k] - E[i].w);
}
}
res[root] += res[E[i].v];
}
// cout << root << ":" << endl;
// for(int i = 0 ; i <= res[root] ; i ++) cout << dp[root][i] << " ";
// cout << endl;
}
int main()
{
while(scanf("%d %d" , &n , &m)!= EOF)
{
id = 0;
mem(head , -1);
mem(dp , 0);
for(int i = 1 ;i <= n ; i ++)
{
for(int j = 1 ; j <= m ;j ++)
dp[i][j] = -MOD;
}
int v , w , up = n - m , num;
for(int i = 1 ; i <= up ; i ++)
{
scanf("%d" , &num);
for(int j = 0 ; j < num ; j ++)
{
scanf("%d %d" , &v , &w);
add(i , v , w);
}
res[i] = 0;
}
for(int i = up+1 ; i <= n ; i ++) {scanf("%d" , &val[i]) ; dp[i][1] = val[i] ; res[i] = 1;}
dfs(1);
for(int i = m ; i >= 0 ; i --)
{
// cout << dp[1][i] << endl;
if(dp[1][i] >= 0)
{
printf("%d\n" , i);
break;
}
}
}
return 0;
}