[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 個點染成白色。將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間距離的和的收益。問收益最大值是多少。題解 首先,看到黑點到黑點 白點與白點,其實這就...