luogu P5021 賽道修建

2022-06-13 12:06:06 字數 1335 閱讀 9933

給定一顆樹(不是二叉樹),在樹上找到$m$條鏈。

求最短鏈的最大值。

其實在考場上想出正解了的。。

就是因為不會stl結果掛了。。

要是寫出來就1=了呢。。

氣死了。

首先因為要求最短鏈的最大值,很容易想到二分。

二分出最短鏈的長度$x$,然後要在樹上找到$m$條長度大於$x$的鏈。

分析問題,每條邊只能用一次,然後可以發現每個點到他的父親點,只能有一條鏈向上傳遞,其他的鏈只能互相組合。

很簡單的貪心,我們要讓這條向上傳遞的鏈最大,其他的鏈組合成盡量多的鏈,使組合成的鏈大於$x$。

如果一條鏈本身就大於$x$,我們直接在總鏈數上累加。

不然記錄下這條鏈。

我在考場上想的是,把所有的鏈記錄下來,然後排序進行雙指標。

這樣好像是$o(n^2logn)$的,而且實現巨煩。。

考場上打了乙個半小時,最終沒有ak day1。。。

回來看到網上的處理方法是用multiset。。

考場上怎麼就沒想到stl呢。。

把所有小於$x$的鏈丟到multiset裡去,每次取出最小的鏈記為$y$,在鏈裡面找出第乙個大於等於$x-y$的鏈,然後同時刪掉這兩條鏈就可以了。

要注意集合裡只有一條鏈的情況。

實現起來巨簡單。。。

氣死我了鴨……

1 #include 2

#define mid ((l+r)>>1)

3using

namespace

std;

4const

int n=5e5+1009;5

intread()

11int

n,m,fa[n],val[n],cnt;

12int head[n],ver[n*2],nxt[n*2],edge[n*2],tot=1;13

int dfs(int x,int

v)23

int maxn=0;24

while(!s.empty())else36}

37return

maxn;38}

39bool check(int

x)44

void build(int x,int

pre)50}

51void add(int u,int v,int

w)55

intmain()

5664 build(1,0

);65

while(l<=r)

69 printf("

%d\n

",r);

70return0;

71 }

view code

luogu P5021 賽道修建

一年前自己還是太菜了。雖然現在也菜。一棵樹,選擇m mm條邊鋪設,要求這些邊不能有交集,且不允許掉頭 我們認為它是從一點修到另外一點的 現在求這些賽道的最短值的最大值。現在看來還是乙個眼題的。二分答案mid midmi d。考慮兒子的資訊通過當前的邊來合併。若當前已經可以更新到mid midmi d...

Luogu P5021 賽道修建

link c 城將要舉辦一系列的賽車比賽。在比賽前,需要在城內修建 m 條賽道。c 城一共有 n 個路口,這些路口編號為 1,2,n 有 n 1 條適合於修建賽道的雙向通行的道路,每條道路連線著兩個路口。其中,第 i 條道路連線的兩個路口編號為 a i 和 b i 該道路的長度為 l i 借助這 n...

洛谷P5021 賽道修建

話說去年為什麼暴力炸成了15.其實我現在都不會做,參考的一位p黨大佬的題解,寫成了c 版而已 附註了一些關鍵部分的細節 總之現在弄懂了qwq includeusing namespace std const int maxn 1e6 10,maxm 2e6 10,inf 1e8 int bg max...