樹DP 樹上染色

2022-03-27 09:32:45 字數 1366 閱讀 3488

[haoi2015]樹上染色

時間限制:1 s 記憶體限制:256 mb

【題目描述】

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

【輸入格式】

第一行兩個整數n,k。

接下來n-1行每行三個正整數fr,to,dis,表示該樹中存在一條長度為dis的邊(fr,to)。輸入保證所有點之間是聯通的。

【輸出格式】

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

【輸入樣例1】

3 1

1 2 1

1 3 2

【輸出樣例1】

3 【資料範圍】

對於30%的資料,n<=20

對於50%的資料,n<=100

對於100%的資料,n<=2000,0<=k<=n

明顯是樹dp,但如果去考慮哪個點是黑點就會很不方便,而任意兩點間的距離過的邊是確定的,那麼可以考慮處理邊,考慮邊對答案的貢獻。對於某條邊,就是l=(他左側黑點×他右側黑點+他左側白點×他右側白點)×邊權。

那麼考慮轉移,我們來挨個向答案中新增子樹,列舉當前子樹中有i個黑點,已列舉完的子樹中共有j個黑點。

g[i+j]=max f[x][j]+f[son][i]+邊權×l;

之前的所有子樹中選j個+當前子樹中選i個+貢獻

必須單開乙個陣列g存當前的,因為還要用的之前的f[x],所以不能馬上轉移。

看似是n^3,實際上列舉不用到m,只要到子樹的大小即可。所以是n^2

#include

#include

#include

#include

#include

#define ll long long

using

namespace

std;

int n,m,e,adj[2005],size[2005];

ll f[2005][2005],g[2005];

struct roadlu[2005*2];

inline

void add(int u,int v,int l);adj[u]=e;}

inline

void dp(int x,int fa)

for(int j=0;j<=m;j++)f[x][j]=g[j],g[j]=0;

size[x]+=size[to];

}}int main()

dp(1,0);

cout

<1][m];

}

樹DP 樹上染色

haoi2015 樹上染色 時間限制 1 s 記憶體限制 256 mb 題目描述 有一棵點數為n的樹,樹邊有邊權。給你乙個在0 n之內的正整數k,你要在這棵樹中選擇k個點,將其染成黑色,並將其他的n k個點染成白色。將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間距離的和的收益。問收益最大...

HAOI2015 樹上染色(樹形dp)

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

樹上染色(樹上揹包dp 複雜度分析)

題幹 有一棵點數為 n 的樹,樹邊有邊權。給你乙個在 0 n 之內的正整數 k,你要在這棵樹中選擇 k 個點,將其染成黑色,並將其他的 n k 個點染成白色。將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間距離的和的收益。問收益最大值是多少。題解 首先,看到黑點到黑點 白點與白點,其實這就...