题目描述
A TV-network plans to broadcast an important football match. Their network of transmitters and users can be represented as a tree. The root of the tree is a transmitter that emits the football match, the leaves of the tree are the potential users and other vertices in the tree are relays (transmitters).
The price of transmission of a signal from one transmitter to another or to the user is given. A price of the entire broadcast is the sum of prices of all individual signal transmissions.
Every user is ready to pay a certain amount of money to watch the match and the TV-network then decides whether or not to provide the user with the signal.
Write a program that will find the maximal number of users able to watch the match so that the TV-network’s doesn’t lose money from broadcasting the match.
题目思路
很简单的一道树状DP题DP[i][j]表示在以i结点为根结点的树当中选择j个用户所要用的最少的费用。则,我们的DP方程式可以写成下面的这个样子。
我们可以将递归的边界设置为k, 这样得到的答案会是一个正确的答案。但是我们知道,一棵子树中所含有的叶子结点的数目有可能会远远的小于叶子结点的总数。为了防止无效的求解,我们采用一个数组来记录当前子树当中叶子结点的数目,来减少迭代的次数。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define MAXN 3005
#define INF -1000005
struct Edge{
int to,len,next;
}EdgeTable[MAXN];
int n,m,e;
int dp[MAXN][MAXN];
int value[MAXN];
int head[MAXN];
int num[MAXN];
void Init()
{
int i,j;
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++){
dp[i][0] = 0;
for(j=1;j<=m;j++)
dp[i][j] = INF;
}
return;
}
void addEdge(int from,int to,int len)
{
EdgeTable[e].to = to;
EdgeTable[e].len = len;
EdgeTable[e].next = head[from];
head[from] = e++;
}
void get_Graph()
{
int i,a,b,t,j;
e = 0;
for(i=1;i<=n-m;i++){
scanf("%d",&t);
for(j=0;j<t;j++){
scanf("%d%d",&a,&b);
addEdge(i,a,b);
}
}
for(i=n-m+1;i<=n;i++){
scanf("%d",&value[i]);
num[i] = 1;
}
return;
}
void Dfs(int cur)
{
int i,j,k;
if(cur > n-m){
dp[cur][1] = value[cur];
return;
}
num[cur] = 0;
for(i=head[cur];i!=-1;i=EdgeTable[i].next){
int dest = EdgeTable[i].to;
Dfs(dest);
num[cur] += num[dest];
for(j=num[cur];j>=1;j--){
dp[cur][j] = max(dp[cur][j],dp[dest][j]-EdgeTable[i].len);
for(k=1;k<j;k++){
dp[cur][j] = max(dp[cur][j],dp[cur][j-k]+dp[dest][k]-EdgeTable[i].len);
}
}
}
return;
}
int main()
{
freopen("input","r",stdin);
int i,ans = 0;
scanf("%d%d",&n,&m);
Init();
get_Graph();
Dfs(1);
for(i=m;i>=1;i--){
if(dp[1][i]>=0){
ans=i;
break;
}
}
printf("%d\n",ans);
return 0;
}