POJ 1155 TELE 树形DP

题意:给你一棵树,root为电视台,每个叶子节点为潜在的用户,其他节点为为讯号传播的中转站,每条边都有权值,如果信号发送到某个叶子节点,将收到用户交的费用,但是经过的边都要消耗费用,问最多能发送到几个用户且不亏本,不赚不亏也算。


对于每个节点,节点的子树都为一个背包,由此进行分组背包即可。


#include <stdio.h>
#include <string.h>
#define INF 1111111111


struct EDGE{
	int to, next, val;
}edge[6666];
int E, head[3333], cnt[3333], dp[3005][3005], n;
void init() {
	memset(head, -1, sizeof(head));
	E = 0;
	int j;
	for(int i = 1;i <= n; i++) {
		dp[i][0] = 0;
		for(j = 1;j <= n; j++)
			dp[i][j] = -INF;
	}
}
void newedge(int u, int v, int val) {
	edge[E].to = v;
	edge[E].val = val;
	edge[E].next = head[u];
	head[u] = E++;
}
void dfs(int u) {
	if(head[u] == -1) {
		cnt[u] = 1;
		return ;
	}
	cnt[u] = 0;
	int i, j, k;
	for(i = head[u];i != -1; i = edge[i].next) {
		int to = edge[i].to;
		dfs(to);
		cnt[u] += cnt[to];
		for(j = cnt[u];j >= 0; j--) {
			if(dp[u][j] == -INF)	continue;
			for(k = 0;k <= cnt[to]; k++) if(j+k <= cnt[u] && dp[u][j] + dp[to][k]-edge[i].val > dp[u][j+k])
				dp[u][j+k] = dp[u][j] + dp[to][k] - edge[i].val;
		}
	}
}
int main() {
	int i, m, k, v, val;
	while(scanf("%d%d", &n, &m) != -1) {
		init();
		for(i = 1;i <= n-m; i++) {
			scanf("%d", &k);
			while(k--) {
				scanf("%d%d", &v, &val);
				newedge(i, v, val);
			}
		}
		for(i = n-m+1;i <= n; i++) {
			scanf("%d", &dp[i][1]);
		}
		dfs(1);
		for(i = cnt[1];i >= 0; i--)	if(dp[1][i] >= 0) {
			printf("%d\n", i);
			break;
		}
	}
	return 0;
}


你可能感兴趣的:(poj,树形DP)