洛谷P3177 樹上染色

2022-05-06 21:24:11 字數 1460 閱讀 6469

題意:

給n,k,n個點的樹,k個點是黑色的,n-k點是白色的

給n-1條u,v,w,收益值是黑點兩兩距離之和,和白點兩兩距離之和的總值

求最大的收益值

思路:因為是樹形的,所以想到了求dp,dp[u][i] 求u為根的選有多少i個黑點的收益值,然後卡殼

翻了題解,發現dp[u][i] 求得是以u為根的 i 個黑點的貢獻值,就是有乙個通式:這條邊左邊的黑點*這條邊右邊的黑點*w+這條邊左邊的白色*這條邊右邊的白點*w

突然就豁然開朗了,仔細想想,我應該……應該個p   笨腦子不可能想到算貢獻的,告辭。這個通式如果是自己想到推出來,可能會吹一輩子

接下來就是在樹裡面進行dp了

f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]+val);

val就是那個通式:

這條邊左邊黑點數:k

這條邊右邊黑點數:k-k

這條邊左邊白點數:sz[v]-k,sz[v]是以u為根連線著 v 點的子樹點數

這條邊右邊的白點數:n-k-(sz[v]-k)

接下來就是類似01揹包操作吧

寫得過程各種wa,tle,參考了別人ac**,修修改改終於ac了

#includeusing

namespace

std;

#define ll long long

#define il inline

#define it register int

#define inf 0x3f3f3f3f

#define lowbit(x) (x)&(-x)

#define mem(a,b) memset(a,b,sizeof(a))

#define mod 1000000007

const

int maxn=2010

;struct

nodea[maxn

<<1

];int

n,k1,cnt,tot,head[maxn];

ll f[maxn][maxn];

int sz[maxn]=;

il void add(int u,int

v,ll w)

void dfs(int u,int

qian)

dfs(v,u);

sz[u]+=sz[v];

}for(it i=head[u];i!=-1;i=a[i].next)

for(it j=min(sz[u],k1);j>=0;j--)}}

}}int

main()

dfs(

1,-1

);

//cout%lld\n

",f[1

][k1]);

return0;

}/*4 11 2 1

1 3 1

1 4 1

6*/

……希望在這條路上多堅持堅持

洛谷P3177 樹上染色

題目 一道非常好的樹形dp。狀態 dp u n 為u的子樹選n個黑點所能得到的收益最大值。則最終的結果就是 dp root k root 可以為任何值,為了方便,使 root 1 然後考慮怎麼狀態轉移,狀態轉移一般要從方程和邊界入手,考慮用揹包的思想,得到方程 dp now j max dp now...

洛谷 P3177 HAOI2015 樹上染色

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

洛谷 P3177 HAOI2015 樹上染色

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