樹上揹包看作分組揹包就好了,收益臨時變成負數也是可以的,並且收益的數值也很大,所以不再讓收益當下標,放到陣列裡儲存,設f[x][t]表示以x為根的子樹中選擇t個人**節目,電視台的最大收益(讓你求什麼反而不一定要存在陣列裡面,可能是設為陣列下標再判斷可行性)
這題比較特殊,一般分組揹包是過不了這麼大資料的,但是因為實際有效的葉子節點十分少,所以可以優化(看注釋)
另外注意f陣列初始值的設定
#include
#include
#include
#include
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const
int maxn =
3000+10
;const
int inf =(1
<<30)
/3;// 這裡十分的坑。。。 一開始寫成1<<30/3 先運算30/3,結果都變成-8了。。。
int n,m,f[maxn]
[maxn]
,last[maxn]
,ans,edge_tot,vis[maxn]
,son[maxn]
;struct edge
edge
(int u,
int v,
int w,
int to):u
(u),
v(v),w
(w),
to(to)
}e[maxn *2]
;inline
void
add(
int u,
int v,
int w)
void
dfs(
int x)
for(
int i=last[x]
; i; i=e[i]
.to)}}
}int
main()
}for
(int i=
1; i<=n; i++
)// f[i][0] = 0; 這裡不設為0是可以的,在上面的轉移中若有選0個的子樹出現一定不會影響已有的最優收益
}for
(int i=n-m+
1; i<=n; i++
)dfs(1
);for(
int i=
0; i<=m; i++)}
printf
("%d\n"
, ans)
;return0;
}
P1273 有線電視網(樹上dp)
某收費有線電視網計畫轉播一場重要的足球比賽。他們的轉播網和使用者終端構成一棵樹狀結構,這棵樹的根結點位於足球比賽的現場,樹葉為各個使用者終端,其他中轉站為該樹的內部節點。從轉播站到轉播站以及從轉播站到所有使用者終端的訊號傳輸費用都是已知的,一場轉播的總費用等於傳輸訊號的費用總和。現在每個使用者都準備...
P1273 有線電視網 樹形DP 樹上揹包
給定一顆有根樹,要求選擇最多的葉子結點,並且使得達到這些葉子結點的花費 可以理解成到葉子的路徑權值和 小於等於選擇的葉子結點的點權和。2 leq n leq 3000 1 leq m leq n 1 經典的樹上揹包問題。可以對一些葉子結點進行選或者不選的決策 以下參考洛谷yqw2486的題解 狀態轉...
題解 P1273 有線電視網
這題顯然是個樹形dp之樹上分組揹包,信心滿滿地寫出轉移方程後,發現 時間複雜度 o n 3 但仔細觀察了討論區和題解後,發現,這是 o n 2 的?於是我開始嘗試牙刷圖 分塊牙刷圖 菊花圖 掃帚圖。卡標算。燃鵝失敗了。證明 暫且先認為所有節點都會產生貢獻,這不會影響最壞複雜。考慮一下最裡面迴圈的過程...