1. 程式人生 > >[LOJ#2478][九省聯考2018]林克卡特樹(樹形DP+帶權二分)

[LOJ#2478][九省聯考2018]林克卡特樹(樹形DP+帶權二分)

Address

洛谷P4383
BZOJ5252
LOJ#2478

Solution

簡版題意:在一棵 n n 個節點的邊帶權樹上刪掉 k k 條邊再加上 k

k 條權為 0 0 的邊組成一棵新樹,最大化新樹的直徑。
容易發現,如果刪掉的 k k 條邊給定,那麼答案就是這 k
+ 1 k+1
個連通塊的直徑之和。
於是問題轉化成在樹上選出 k + 1 k+1 條不相交的路徑的最大權值和。點視為退化的路徑。
樹形 DP : f
[ u ] [ i ] [ 0 / 1 / 2 ] f[u][i][0/1/2]
表示 u u 的子樹內選出 i i 條路徑,根的度數為 0 0 1 1 2 2 的最大收益。
注:特殊情況:如果 u u 沒有被選出則度數為 0 0 ,如果 u u 單獨作為一條路徑則度數為 1 1
轉移即列舉子節點 v v 進行各種討論,設 f f' v v 之前的 DP 陣列。下面我們先不考慮 u u 單獨作為一條路徑的情況。
f [ u ] [ i + j ] [ s ] = max ( f [ u ] [ i + j ] [ s ] , f [ u ] [ i ] [ s ] + f [ v ] [ j ] [ t ] ) f[u][i+j][s]=\max(f[u][i+j][s],f'[u][i][s]+f[v][j][t])
其中 s s t t [ 0 , 2 ] Z [0,2]\cap\Z 內任意數。
f [ u ] [ i + j ] [ 1 ] = max ( f [ u ] [ i + j ] [ 1 ] , f [ u ] [ i ] [ 0 ] + f [ v ] [ j ] [ 1 ] + l e n ( u , v ) ) f[u][i+j][1]=\max(f[u][i+j][1],f'[u][i][0]+f[v][j][1]+len(u,v))
其中 l e n ( u , v ) len(u,v) 為邊 ( u , v ) (u,v) 的權。
f [ u ] [ i + j 1 ] [ 2 ] = max ( f [ u ] [ i + j 1 ] [ 2 ] , f [ u ] [ i ] [ 1 ] + f [ v ] [ j ] [ 1 ] + l e n ( u , v ) ) f[u][i+j-1][2]=\max(f[u][i+j-1][2],f'[u][i][1]+f[v][j][1]+len(u,v))
最後算上 u u 單獨作為一條路徑的貢獻,還是一樣的樹形揹包。這裡略去。
最後答案:
max ( f [ u ] [ k + 1 ] [ 0 ] , f [ u ] [ k + 1 ] [ 1 ] , f [ u ] [ k + 1 ] [ 2 ] ) \max(f[u][k+1][0],f[u][k+1][1],f[u][k+1][2])
複雜度 O ( n k ) O(nk) O ( n 2 ) O(n^2)
而對於包含「 k k 個」這樣約束的問題,我們可以考慮使用帶權二分(又稱 wqs 二分、凸優化)去掉「 k k 個」的約束。
如果你有興趣將 i 從 1 到 k+1 把 max(f[u][i][0],f[u][i][1],f[u][i][2]) 的值全部打出來, 可以發現這是一個單峰函式,在最大值左邊遞增,右邊遞減。然後如果你還有興趣將打出來的陣列進行差分, 那麼又可以發現差分後的陣列是單調遞減的。
我們考慮給每條路徑加上一個權值 m i d mid
m i d mid\rightarrow-\infty 時,最優方案是隻選一條路徑。
m i d + mid\rightarrow+\infty 時,最優方案是選出 n n 條只包含一個點的路徑。
並且隨著 m i d mid 的增加,最優方案選出的路徑數單調不減。
所以我們二分 m i d mid f f 去掉第二維後轉移方程變成:
f [ u ] [ s ] = max ( f [ u ] [ s ] , f [ u ] [ s ] + f [ v ] [ t ] ) f[u][s]=\max(f[u][s],f'[u][s]+f[v][t])
f [ u ] [ 1 ] = max ( f [ u ] [ 1 ] , f [ u ] [ 0 ] + f [ v ] [ 1 ] + l e n ( u , v ) ) f[u][1]=\max(f[u][1],f'[u][0]+f[v][1]+len(u,v))
f [ u ] [ 2 ] = max ( f [ u ] [ 2 ] , f [ u ] [ 1 ] + f [ v ] [ 1 ] + l e n ( u , v ) m i d ) f[u][2]=\max(f[u][2],f'[u][1]+f[v][1]+len(u,v)-mid)