Luogu P5021 賽道修建

2022-05-04 13:27:10 字數 1478 閱讀 4274

\(link\)

\(c\)城將要舉辦一系列的賽車比賽。在比賽前,需要在城內修建\(m\)條賽道。

\(c\)城一共有\(n\)個路口,這些路口編號為\(1,2,…,n\),有\(n−1\)條適合於修建賽道的雙向通行的道路,每條道路連線著兩個路口。其中,第\(i\)條道路連線的兩個路口編號為\(a_i\)和\(b_i\)​,該道路的長度為\(l_i\)​。借助這\(n-1\)條道路,從任何乙個路口出發都能到達其他所有的路口。

一條賽道是一組互不相同的道路\(e_1,e_2,…,e_k\),滿足可以從某個路口出發,依次經過道路\(e_1,e_2,…,e_k\)​(每條道路經過一次,不允許調頭)到達另乙個路口。一條賽道的長度等於經過的各道路的長度之和。為保證安全,要求每條道路至多被一條賽道經過。

目前賽道修建的方案尚未確定。你的任務是設計一種賽道修建的方案,使得修建的\(m\)條賽道中長度最小的賽道長度最大(即\(m\)條賽道中最短賽道的長度盡可能大)

首先看到最小的最大,就想到要二分。我們二分\(m\)條賽道中長度最小的賽道長度\(mid\),那麼\(check\)的就是長度\(\ge\)的賽道最多能不能\(\ge\),如果可以,那麼\(l=mid+1\),否則\(r=mid-1\)。

這個還是可以想到的,就是\(check\)不太好寫。注意到對於某個節點\(x\)和它的乙個子節點\(y\),一定是選若干條以\(y\)為鏈頂的鏈,將剩下的最短的鏈\(l_1\)和對應最短的滿足\(len_1+len_2\ge\)的鏈\(l_2\)拼成一條賽道,然後如果最後還剩下一條鏈\(l_3\),長度就一定是最大的,將它和\(x\rightarrow\)這條邊拼在一起,構成一條賽道。

這其實就是貪心的思想。因為\(x\rightarrow\)這條邊一定能且只能和一條以\(y\)為頂的鏈構成賽道,然後如果把某條\(l_1\)對應的\(l_2\)替換成更大的,可能反而會找不到一條鏈\(l_3\),滿足\(len_3+len_}\ge\)。

具體實現用\(multiset\)。

#include using namespace std;

int n, m, tot, res, sum, l = 1e9, r, hd[50005], to[100005], nxt[100005], w[100005];

multiset < int > g[50005];

int read()

while (ch >= '0' && ch <= '9')

return x * fl;

}void add(int x, int y, int z)

int dfs(int x, int fa, int d)

int mx = 0;

while (g[x].size())

return mx;

}int check(int x)

int main()

while (l <= r)

printf("%d\n", res);

return 0;

}

luogu P5021 賽道修建

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

luogu P5021 賽道修建

給定一顆樹 不是二叉樹 在樹上找到 m 條鏈。求最短鏈的最大值。其實在考場上想出正解了的。就是因為不會stl結果掛了。要是寫出來就1 了呢。氣死了。首先因為要求最短鏈的最大值,很容易想到二分。二分出最短鏈的長度 x 然後要在樹上找到 m 條長度大於 x 的鏈。分析問題,每條邊只能用一次,然後可以發現...

洛谷P5021 賽道修建

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