洛谷1273 有線電視網(樹上揹包)

2022-05-14 15:30:09 字數 1235 閱讀 1492

點此看題面

大致題意:給你一棵帶權樹,已知每連線一條邊需要一定花費,如果某個葉節點能到達根,可以獲得一定收益。問在不虧本的情況下,最多能使多少個葉節點能到達根。

這是一道比較經典的樹上揹包題。

我們可以用\(f_\)表示在以\(i\)為根的子樹內選擇\(j\)個葉節點能得到的最大收益,並用\(size_i\)表示以\(i\)為根的子樹內的葉節點數目

那麼答案就是找到乙個最大的\(ans\)使得\(f_≥0\)。

樹上揹包的轉移與普通揹包是十分相似的:

\[f_=max(f_,f_+f_-val)

\]其中\(val\)表示這條邊的邊權。

注意\(j\)和\(k\)的列舉範圍,其中\(1≤j≤size_x+size_,1≤k≤size_\)。

雖然複雜度看似\(o(n^3)\)的,但實際上是達不到上界的,於是雖然\(1≤n≤3000\),依然能輕鬆跑過。

#include#define max(x,y) ((x)>(y)?(x):(y))

#define min(x,y) ((x)<(y)?(x):(y))

#define uint unsigned int

#define ll long long

#define ull unsigned long long

#define swap(x,y) (x^=y,y^=x,x^=y)

#define abs(x) ((x)<0?-(x):(x))

#define inf 1e9

#define inc(x,y) ((x+=(y))>=mod&&(x-=mod))

#define ten(x) (((x)<<3)+((x)<<1))

#define n 3000

#define add(x,y,z) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].val=z)

using namespace std;

int n,m,ee=0,lnk[n+5],val[n+5];

struct edge

e[n+5];

class fio

}public:

inline int getans()

}treedp;

int main()

P1273 有線電視網 樹上揹包

樹上揹包看作分組揹包就好了,收益臨時變成負數也是可以的,並且收益的數值也很大,所以不再讓收益當下標,放到陣列裡儲存,設f x t 表示以x為根的子樹中選擇t個人 節目,電視台的最大收益 讓你求什麼反而不一定要存在陣列裡面,可能是設為陣列下標再判斷可行性 這題比較特殊,一般分組揹包是過不了這麼大資料的...

洛谷P1273 有線電視網 樹上分組揹包

某收費有線電視網計畫轉播一場重要的足球比賽。他們的轉播網和使用者終端構成一棵樹狀結構,這棵樹的根結點位於足球比賽的現場,樹葉為各個使用者終端,其他中轉站為該樹的內部節點。從轉播站到轉播站以及從轉播站到所有使用者終端的訊號傳輸費用都是已知的,一場轉播的總費用等於傳輸訊號的費用總和。現在每個使用者都準備...

題解 洛谷P1273 有線電視網(樹上分組揹包)

次元傳送門 洛谷p1273 一開始想的是普通樹形dp 但是好像實現不大好 觀摩了一下題解 是樹上分組揹包 設f i j 為以i為根的子樹中取j個客戶得到的總價值 我們可以以i為根有j組 在每一組中分別又取1個,2個,3個.n個客戶 化為揹包思想即j為一共有j組揹包容量為每組的客戶數總和 把該節點的每...