傳送門
考場上把暴力都打滿了,結果檔案輸入輸出寫錯了....
當時時間很充裕,如果認真想想正解是可以想出來的..
問你 長度最小的賽道長度的最大值
顯然二分答案
考慮如何判斷是否可行
顯然對於乙個節點,它最多只能向父親傳一條路徑長度
那麼其它路徑的合併只能在子樹間進行
貪心一波,如果一段路徑在子樹就可以合併出合法長度
那麼直接合併一定是不會比傳給父親再考慮合併更劣的
子樹都合併完後,剩下的肯定傳最長的長度給父親
考慮在子樹內如何貪心地進行最優合併
顯然最小的邊去找最小的能使它合法的邊合併
(注意不是最大的邊去找最小的能使它合法的邊合併)
那麼用乙個multiset存一下當前節點的各個邊長
然後就按前面的方法乙個個合併就好了
注意和並時的一些細節和二分的上界,(因為multiset常數大,所以要把上界設為總長除賽道數)
#include#include#include
#include
#include
#include
using
namespace
std;
typedef
long
long
ll;const
int n=1e5+7,inf=2e9+7
;inline
intread()
while(ch>='
0'&&ch<='
9')
return x*f;
}int fir[n],from[n<<1],to[n<<1],val[n<<1
],cntt;
inline
void add(int &a,int &b,int &c)
intn,m,mid,cnt;
intf[n];
multiset
s;multiset
::iterator it,itt,pit;
void dfs(int x,int
fa) s.clear();
//記得清空
for(int i=fir[x];i;i=from
[i])
it=s.begin();
while(it!=s.end())
f[x]=0;/*
記得先清空f
*/ it=s.begin(); if(s.end()!=it) it=s.end(),it--,f[x]=*it;//
注意必須有邊傳才更新f
}inline
intjudge()
intmain()
int l=0,r=s/m;
while(r-l>1
)
mid=r;
printf("%d
",judge() ?r : l);
return0;
}
洛谷P5021 賽道修建
話說去年為什麼暴力炸成了15.其實我現在都不會做,參考的一位p黨大佬的題解,寫成了c 版而已 附註了一些關鍵部分的細節 總之現在弄懂了qwq includeusing namespace std const int maxn 1e6 10,maxm 2e6 10,inf 1e8 int bg max...
P5021 賽道修建 貪心 二分
c 城將要舉辦一系列的賽車比賽。在比賽前,需要在城內修建 mm 條賽道。c 城一共有 nn 個路口,這些路口編號為 1,2,n1,2,n,有 n 1n 1 條適合於修建賽道的雙向通行的道路,每條道路連線著兩個路口。其中,第 ii 條道路連線的兩個路口編號為 a ia i 和 b ib i,該道路的長...
NOIP2018 P5021 賽道修建
看到題意描述第一反應就是先二分那個修建的 mm 條賽道中長度最小的賽道的長度 k 然後 o n o n 或 o n log n o nlogn 判斷。那麼怎麼判斷呢?對於每個結點,把所有傳上來的值 valval 放進乙個 multisetmultiset 其實這些值對答案有貢獻就兩種情況 val k...