題目鏈結:
題目大意:電視台轉播節目。對於每個根,其子結點可能是使用者,也可能是中轉站。但是使用者肯定是葉子結點。傳到中轉站或是使用者都要花錢,如果是使用者,則還可以收錢。問在不虧本的前提下最多能有多少個使用者看到節目。
解題思路:
比較麻煩的樹形揹包。首先cost=1。
花的錢權在邊,收的錢權在點,且是葉子結點。所以首先可以對葉子結點進行預處理。
用dp[i][j]表示在i點時傳播j個使用者(包含自身),則dp[n-m-1~n][1]=每個使用者繳費。
這樣在dfs的時候就可以專心處理邊權問題。兩個for迴圈這麼寫:
for(f...j...cost)
for(0...k...j)
則轉移方程就是dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[t][k]-e[a].w);
這裡之所以是f而不是f+1,是因為中轉站不是使用者,不需要cost。f+=dfs(t)。
對於如何知道在不虧本的情況下的最多使用者,在dfs之後,從dp[1][m..0]開始找乙個大於0的最大m值。
如果你熟悉傳統的樹形揹包的話,就會發現這裡不能每次都使用最大揹包容量m迴圈了,不然會tle,原因是這題m比較大,每次都從m開始不t就怪了。
所以必須採用這種cost=1時特殊的當前最大容量f。
#include "cstdio
"#include
"iostream
"#include
"cstring
"using
namespace
std;
#define maxn 3005
#define inf 0x3f3f3f3f
struct
edge
e[maxn];
int leaf[maxn],dp[maxn][maxn],get
[maxn],head[maxn];
intn,m,k,v,w,tol;
void addedge(int u,int v,int
w)int dfs(int
root)
returnf;}
intmain()
}for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
dp[i][j]=-inf;
for(int i=n-m+1;i<=n;i++)
dfs(1);
for(int i=m;i>=0;i--)
}}
13540208
neopenx
1155
accepted
33704k
157ms
c++1322b
2014-10-18 00:48:42
POJ 1155 TELE (樹形DP,樹形揹包)
題意 給定一棵樹,n個節點,其中有m個葉子表示的是使用者,其他點表示中轉器,每條邊都有權值,每個使用者i願意給的錢w i 問如果在不虧錢的情況下能為多少使用者轉播足球比賽?思路 其實就是要選出部分葉子節點,其花費 所選葉子權值 經過的所有邊權 每條邊只算1次花費 那麼對於每個節點,可以考慮在其子樹下...
poj1155 TELE(樹形 揹包dp)
題意 某電台要廣播一場比賽,該電台網路是由n個網點組成的一棵樹,其中m個點為客戶端,其餘點為 站。客戶端i願支付的錢為pay i 每一條邊需要的花費固定,問電台在保證不虧損的情況下,最多能使多少個客戶端接收到資訊?思路 設dp i j 表示i節點為根節點並且子樹已經有j個使用者的時候最大剩餘費用。那...
POJ 1155 TELE 樹形揹包
1為根節點,有m個葉節點,其他為中間結點,每個結點的權值代表他願意付出的錢,邊的權值代表聯通兩節點的代價,求不虧損的情況下最多能到達多少個葉節點。另dp u i 表示根節點為u的子樹此時裝了i個葉節點的盈利情況 m oney i e dgec osti 那麼我們就能得到這樣的狀態轉移方程 如果u是葉...