題解 LuoGu2680 運輸計畫

2021-09-24 05:24:50 字數 1314 閱讀 8045

原題傳送門

去年覺得是道難題,現在覺得這著實是道大水題

題意:一棵樹,給出幾條路徑(從點x到點y),可以使一條邊長度變為0,使得路徑長度最大值最小

思路:

就搞定了

接著想如何實現

總結:noip的題目還是很可以的,演算法、思維難度不高,應用性還是比較強的

用到了許多小演算法:lca,二分,樹上差分

code:

#include

#define maxn 300010

using

namespace std;

struct edgeedge[maxn <<1]

;struct lineline[maxn]

;int num, size[maxn]

, cnt, son[maxn]

, fa[maxn]

, d[maxn]

, head[maxn]

, len[maxn]

, top[maxn]

, power[maxn]

;int sum, maxlen, n, m;

inline

intread()

void

addedge

(int x,

int y,

int z)

void

dfs(

int u)}}

void

dfs(

int u,

int x)

}int

lca(

int u,

int v)

if(d[u]

< d[v]

)swap

(u, v)

;return v;

}void

dfs1

(int u,

int l)}if

(power[u]

== cnt) sum =

max(sum, l);}

bool

check

(int mid)

intmain()

dfs(1)

;dfs(1

,0);

for(

int i =

1; i <= m;

++i)

int l =

0, r = maxlen, ans =0;

while

(l <= r)

printf

("%d\n"

, ans)

;return0;

}

luogu2680 運輸計畫

很明顯,由於是求最長路的最小值,我們可以使用二分求解.我們二分乙個長度 mid 將所有使得 dis u,v 大於 mid 的點對 u,v 找出,設總共有 m 條這樣的邊,那麼我們需要改變的改變邊一定是被這 m 條邊都經過的邊,所以我們只需要找到滿足這個要求的長度最大的改變邊使得這 m 條邊中最長的一...

Luogu2680 運輸計畫

我們對每條邊 i 單獨考慮,那麼設 v i 為這條邊的長度,經過它的路徑長度集合為 s 未經過它的路徑長度集合為 t ans i max begin s v i t end ans min ans i 對於 s 我們直接對於一條長度為 l 的路徑,該路徑上的邊都對 l 取 max 用樹鏈剖分很容易處...

luogu2680 運輸計畫

首先二分列舉答案t,考慮刪去的邊應滿足的條件 所有大於 t的鏈全部經過且長度不小於最長鏈 t,第二個條件很好判斷,考慮第乙個條件。先考慮有祖先 後代關係的鏈,用如果把這條鏈到 1看成乙個序列,那麼差分一下再 dfs一遍就可以對這條鏈上每乙個點打上標記。然後沒有祖先 後代關係的鏈,同樣可以分解成兩條鏈...