[POJ1155]TELE

试题描述

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.

输入

The first line of the input file contains two integers N and M, 2 <= N <= 3000, 1 <= M <= N-1, the number of vertices in the tree and the number of potential users. 
The root of the tree is marked with the number 1, while other transmitters are numbered 2 to N-M and potential users are numbered N-M+1 to N. 
The following N-M lines contain data about the transmitters in the following form: 
K A1 C1 A2 C2 ... AK CK 
Means that a transmitter transmits the signal to K transmitters or users, every one of them described by the pair of numbers A and C, the transmitter or user‘s number and the cost of transmitting the signal to them. 
The last line contains the data about users, containing M integers representing respectively the price every one of them is willing to pay to watch the match.

输出

The first and the only line of the output file should contain the maximal number of users described in the above text.

输入示例

9 6
3 2 2 3 2 9 3
2 4 2 5 2
3 6 2 7 2 8 2
4 3 3 3 1 1

输出示例

5

数据规模及约定

见“输入”;另:过程中不会有超过 int 的值。

题解

树形 dp(树上背包)。

设 f(i, j) 表示子树 i 中选择了 j 个叶子的最大获利(若为负则 -f(i, j) 为最小亏损)。那么答案就是最大的 j,满足 f(i, j) 非负。

考虑子树 u,儿子上的信息肯定是最有子结构,所以先算出所有的 f(son, j),然后分别将一个个子树的信息加入 f(i, j)(f(u, i+j) = max{ f(u, i) + f(son, j) - dist(i, son) | j > 0 , f(u, i) + f(son, j) | j = 0 })。

可以证明总转移数是 O(n2) 级别的,详见这里

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;

const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
	if(Head == Tail) {
		int l = fread(buffer, 1, BufferSize, stdin);
		Tail = (Head = buffer) + l;
	}
	return *Head++;
}
int read() {
	int x = 0, f = 1; char c = Getchar();
	while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = Getchar(); }
	while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = Getchar(); }
	return x * f;
}

#define maxn 3010
#define oo 2147483647

int n, usr, m, head[maxn], nxt[maxn], to[maxn], dist[maxn], pay[maxn];

void AddEdge(int a, int b, int c) {
	to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
	return ;
}

int f[maxn][maxn], clea[maxn];
void dp(int u) {
	if(u > n - usr) {
		clea[u] = 1;
		f[u][0] = 0; f[u][1] = pay[u];
		return ;
	}
	f[u][0] = 0;
	for(int e = head[u]; e; e = nxt[e]) {
		dp(to[e]);
		for(int i = clea[u]; i >= 0; i--) if(f[u][i] < oo)
			for(int j = 0; j <= clea[to[e]]; j++) if(f[to[e]][j] < oo)
				f[u][i+j] = max(f[u][i+j], f[u][i] + f[to[e]][j] - (j ? dist[e] : 0));
		clea[u] += clea[to[e]];
	}
	return ;
}

int main() {
	n = read(); usr = read();
	for(int i = 1; i <= n - usr; i++) {
		int k = read();
		while(k--) {
			int u = read(), c = read();
			AddEdge(i, u, c);
		}
	}
	for(int i = n - usr + 1; i <= n; i++) pay[i] = read();

	for(int i = 1; i <= n; i++)
		for(int j = 0; j <= n; j++) f[i][j] = -oo;
	dp(1);

	for(int j = clea[1]; j; j--) if(f[1][j] >= 0) return printf("%d\n", j), 0;
	puts("0");

	return 0;
}
时间: 2024-11-15 03:04:16

[POJ1155]TELE的相关文章

POJ1155 TELE(树形DP)

题目是说给一棵树,叶子结点有负权,边有正权,问最多能选多少个叶子结点,使从叶子到根的权值和小于等于0. 考虑数据规模表示出状态:dp[u][k]表示在u结点为根的子树中选择k个叶子结点的最小权值 最后就从d[1][k]中找满足的最大的k.不过单这样转移时间复杂度是指数级,显然这题就是用树上背包了. 不过其实这题时间复杂度不会算= =反正感觉挺靠谱,交了就AC了.. 又做了一道树上背包,HDU1561和POJ3345. 1 #include<cstdio> 2 #include<cstri

POJ-1155 TELE (树形DP+分组背包)

题目大意:给一棵带边权的有根树,每个叶子节点有权.边权表示代价,叶子节点的权值代表可以补偿多少代价.问从根节点最多可以到达多少个叶子,使得付出的总代价不大于0. 题目分析:定义状态dp(u,k)表示从u开始到达k个叶子所花费的最小代价.则状态转移方程为: dp(u,k)=min(dp(u,k),dp(son,j)+dp(u,k-j)+u到son的代价). ps:要加上优化,否则超时. 代码如下: # include<iostream> # include<cstdio> # inc

【树形dp】TELE

[POJ1155]TELE Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5376   Accepted: 2973 Description A TV-network plans to broadcast an important football match. Their network of transmitters and users can be represented as a tree. The root o

POJ 1155 TELE

TELE Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: 115564-bit integer IO format: %lld      Java class name: Main A TV-network plans to broadcast an important football match. Their network of transmitters an

树形DP [POJ 1155] TELE

TELE Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3787   Accepted: 2007 Description 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 tre

POJ 1155 TELE 树形背包问题

题目描述看的莫名其妙,很久才看懂. 就是很裸的树形背包问题吧,状态是dp(i,j)表示节点i取到j个客户能得到的最大收益. 注意一开始初始化的时候所有j为0的时候应该是0,然后其他值都要初始化成负无穷,因为收益有可能是负值. 然后做01背包的时候注意方向,防止出现取某一个元素多次 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set&g

POJ 1155 TELE 背包型树形DP 经典题

由电视台,中转站,和用户的电视组成的体系刚好是一棵树 n个节点,编号分别为1~n,1是电视台中心,2~n-m是中转站,n-m+1~n是用户,1为root 现在节点1准备转播一场比赛,已知从一个节点传送数据到达另一个节点,电视台需要一定的费用 若可以传送数据到达用户的节点n-m+1~n,这些用户各自愿意支付一定的费用给电视台 现在电视台希望在不亏本的情况下为尽量多的用户转播比赛 输出最多可以为多少用户转播比赛 背包类型的树形DP第一题 dp[i][j]表示以节点i为根的子树有j个用户获得转播,电视

poj1155 树上的背包

题目链接:http://poj.org/problem?id=1155 题意:给定一棵树,1为根结点表示电视台,有m个叶子节点表示客户,有n-m-1个中间节点表示中转站,每条树边有权值.现在要在电视台播放一场比赛,每个客户愿意花费cost[i]的钱观看,而从电视台到每个客户也都有个费用,并且经过一条边只会产生一个费用.问电视台不亏损的情况最多有几个客户可以看到比赛? 思路:在树上的背包,具体看代码注释. 代码: #include<iostream> #include<cstdio>

poj1155

题意:给定一个树形图,节点数量3000.叶子节点是用户,每个用户如果能看上电视会交一定的电视费.看上电视的条件是从根到该用户的路径全部被修好,修每条边有一个费用.在不亏损(用户交钱总额>=修路总费用)的前提下,最多有多少人能看上电视. 分析:树形dp.dp[u][i][j]表示对于u节点,只看其前i个儿子对应的子树,在这些子树中总共让j个用户看上电视,这样的最大利润是多少(可以为负值). 那么dp[u][i][j]=max(dp[u][i-1][j], dp[v][num[v][k] + dp[