HAOI2015 樹上染色 洛谷 3177

2021-08-08 13:23:40 字數 995 閱讀 7366

然後無根樹轉有根樹。

設f[x][j]表示以x為根的子樹,選取了j個黑點,連線x和father[x]的這條邊最大的貢獻。然後揹包一下就好了。

- 詳細一點,對於這條邊。子樹下有

j 個黑點,那麼在其他位置就有k−

j個黑點,所以由於黑點這條邊被走過j×

(k−j

) 次。子樹下有si

ze[x

]−j 個白點,其他位置有n−

k−si

ze[x

]+j 個白點,所以由於白點這條邊被走過(s

ize[

x]−j

)×(n

−k−s

ize[

x]+j

) 次。

#include 

#define ll long long

using

namespace

std ;

void read ( ll &x, char c = getchar() )

const ll maxn = 2005 ;

ll n, m, e, be[maxn], size[maxn], nxt[maxn<<1], to[maxn<<1], w[maxn<<1], f[maxn][maxn] ;

void add ( ll x, ll y, ll z )

void dfs ( ll x, ll from, ll father )

for ( i = be[x] ; i ; i = nxt[i] )

for ( j = 0 ; j <= size[x] && j <= m ; j ++ )

}int main()

dfs(1, 0, 1) ;

ll ans = 0 ;

ans = max(ans, f[1][m]) ;

printf ( "%lld\n", ans ) ;

return

0 ;}

HAOI2015 樹上染色

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

HAOI2015 樹上染色

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

HAOI2015 樹上染色

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