原題傳送門
去年覺得是道難題,現在覺得這著實是道大水題
題意:一棵樹,給出幾條路徑(從點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一遍就可以對這條鏈上每乙個點打上標記。然後沒有祖先 後代關係的鏈,同樣可以分解成兩條鏈...