HAOI2015 樹上染色

2021-10-08 12:09:43 字數 1384 閱讀 1610

考慮子樹當中所有邊的貢獻即可。然後就能簡單做樹上揹包了。

但是要注意列舉的順序,應該從大到小更新,否則某個狀態會多次被加。

如果不想考慮列舉順序,那麼直接dp的時候用乙個臨時陣列記錄。

ac**:

#pragma gcc optimize("-ofast","-funroll-all-loops")

#include

#define int long long

using namespace std;

const

int n=

2e3+

10,m=n<<1;

int n,k,dp[n]

[n],sz[n]

;int head[n]

,nex[m]

,to[m]

,w[m]

,tot;

void

add(

int a,

int b,

int c)

void

dfs(

int x,

int fa)

sz[x]

+=sz[to[i]];

}}signed

main()

不考慮順序:

#pragma gcc optimize("-ofast","-funroll-all-loops")

#include

#define int long long

using namespace std;

const

int n=

2e3+

10,m=n<<1;

int n,k,dp[n]

[n],sz[n]

;int head[n]

,nex[m]

,to[m]

,w[m]

,tot;

void

add(

int a,

int b,

int c)

void

dfs(

int x,

int fa)

;for

(int j=

0;j<=

min(sz[x]

,k);j++

)for

(int k=

0;k<=sz[to[i]

]&&k+j<=k;k++

)for

(int j=

0;j<=k;j++

) dp[x]

[j]=f[j]

; sz[x]

+=sz[to[i]];

}}signed

main()

HAOI2015 樹上染色

有一棵點數為 n 的樹,樹邊有邊權。給你乙個在 0 n 之內的正整數k,你要在這棵樹中選擇 k 個點,將其染成黑色,並將其他的 n k個點染成白色。將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間距離的和的收益。問收益最大值是多少。輸入第一行兩個整數 n,k。接下來 n 1 行每行三個正整...

HAOI2015 樹上染色

嘟嘟嘟 首先這一眼看出來,要樹形dp。然後發現狀態不好設,剛開始我想的是dp i j 表示以 i 為根的子樹,選了 j 個黑點的最大價值。結果就不會轉移了。轉移的時候想考慮 這一條邊的貢獻,但是發現這個狀態的轉移所涉及的不只是這一條邊,還有子樹中的邊,於是就徹底gg了。還是看了題解。題解也是考慮貢獻...

HAOI2015 樹上染色

有一棵點數為 n 的樹,樹邊有邊權。給你乙個在 0 n 之內的正整數 k 你要在這棵樹中選擇 k個點,將其染成黑色,並將其他 的n k個點染成白色 將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間的距離的和的受益。問受益最大值是多少。輸入格式 第一行包含兩個整數 n,k 接下來 n 1 行...