HAOI2015 樹上染色

2021-09-29 05:43:08 字數 1210 閱讀 3567

有一棵點數為 n 的樹,樹邊有邊權。給你乙個在 0∼n 之內的正整數k,你要在這棵樹中選擇 k 個點,將其染成黑色,並將其他的 n−k個點染成白色。將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間距離的和的收益。

問收益最大值是多少。

輸入第一行兩個整數 n,k。

接下來 n−1 行每行三個正整數 fr,to,dis,表示該樹中存在一條長度為 dis 的邊 (fr,to)

輸入保證所有點之間是聯通的。

輸出輸出乙個正整數,表示收益的最大值。

樣例輸入 [複製]

5 21 2 3

1 5 1

2 3 1

2 4 2

樣例輸出 [複製]

17思路

樹形dp

size[i]:i子樹的節點個數

f[i][j]:在i子樹中染j個黑點的最大貢獻

更新時考慮每條邊對答案的貢獻

即:這條邊兩側的黑點個數乘積邊權+兩側白點個數乘積邊權

#include

using

namespace std;

#define int long long

inline

intread()

const

int n=

2010

;int n,k;

struct nodee[n<<1]

;int fir[n]

,cnt=

0,dp[n]

[n],siz[n]

;inline

void

add(

int u,

int v,

int w)

;fir[u]

=cnt;

}inline

intcalc

(int w,

int siz,

int y)

inline

void

dfs(

int u,

int fa)

} siz[u]

+=siz[v];}

}signed

main()

dfs(1,

0);int ans=dp[1]

[k];

printf

("%lld"

,ans)

;return0;

}

HAOI2015 樹上染色

考慮子樹當中所有邊的貢獻即可。然後就能簡單做樹上揹包了。但是要注意列舉的順序,應該從大到小更新,否則某個狀態會多次被加。如果不想考慮列舉順序,那麼直接dp的時候用乙個臨時陣列記錄。ac pragma gcc optimize ofast funroll all loops include defin...

HAOI2015 樹上染色

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

HAOI2015 樹上染色

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