洛谷P3177 樹上染色

2022-03-17 16:03:02 字數 998 閱讀 8434

題目

一道非常好的樹形dp。

狀態:\(dp[u][n]\)為u的子樹選n個黑點所能得到的收益最大值。

則最終的結果就是\(dp[root][k],\)

\(root\)可以為任何值,為了方便,使\(root=1\)

然後考慮怎麼狀態轉移,狀態轉移一般要從方程和邊界入手,考慮用揹包的思想,得到方程:

\[dp[now][j]=max(dp[now][j], dp[now][j-l]+dp[to][l]+子樹選l個黑點的貢獻)

\]\((0<=j<=min(k, size[now]), 0<=l<=min(j,size[to]))\)

接下來問題轉化為如何求他們的貢獻

根據題意,貢獻就是(黑點的距離和+白點的距離和)=(黑節點數\(*\)另一端黑節點邊權+白節點數\(*\)另一端白節點邊權)\(*\)e[i].len.

\(e[i].len * ( (k - l) * l + (siz[to] - l) * (n - k - siz[to] + l) )\)

且這只能由\(dp[now][j-l]\)已被更新的情況下才可以更新。

#include #define int long long

using namespace std;

int n, k, cnt, root, lin[3010], vis[3010], siz[3010], dp[3010][3010];//每個點的最短路

struct edg e[4001011];

inline void add(int f, int t, int l)

void init(int now, int fa, int de)

return;

} void dfs(int now, int fa)

//此時他的子樹都已經搜尋完了。

for (int i = lin[now]; i; i = e[i].nex)

}}signed main()

洛谷P3177 樹上染色

題意 給n,k,n個點的樹,k個點是黑色的,n k點是白色的 給n 1條u,v,w,收益值是黑點兩兩距離之和,和白點兩兩距離之和的總值 求最大的收益值 思路 因為是樹形的,所以想到了求dp,dp u i 求u為根的選有多少i個黑點的收益值,然後卡殼 翻了題解,發現dp u i 求得是以u為根的 i ...

洛谷 P3177 HAOI2015 樹上染色

懶得複製題面了直接傳送門吧 直接求點與點之間的距離感覺不是很好求,所以我們考慮換乙個求法。瞄了一眼題解 距離跟路徑上邊的長度有關,所以我們直接來看每一條邊的貢獻吧 這誰想得到啊 對於每一條邊,它的貢獻等於 一邊的白點數 另一邊的白點數 一邊的黑點數 另一邊的黑點數 邊權 然後。我又卡住了。再次瞄題解...

洛谷 P3177 HAOI2015 樹上染色

有一棵點數為 n 的樹,樹邊有邊權。給你乙個在 0 n 之內的正整數 k 你要在這棵樹中選擇 k 個點,將其染成黑色,並將其他 的 n k 個點染成白色 將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間的距離的和的受益。問受益最大值是多少。有點難想的dp 我果然太菜了 stdcall f ...