NOIP2018 Day1 T3 賽道修建 - 二分套二分 - dp - 貪心
阿新 • • 發佈:2018-11-26
場上心路歷程:
首先這顯然好像是個dp。臥槽這個題能多項式?
考慮了一會列了個部分分表,發現我會做m=1求直徑,會做鏈,還以為會做星星。
嗯確定了一定是dp,一定要二分答案。
然後寫完暴力開始寫鏈的時候突然想,誒星星怎麼做來著???
仔細冷靜了一下發現星星想得有問題。
開始慌,寫了一半的鏈棄。
冷靜了一下想起了以前cf做的一個題,當時讀錯題了,在讀錯題的基礎上有人跟我說了個錯誤做法,當時大意是dp的第二維狀態可以貪心,不過對那個錯題是錯結論。
猜測了二分答案後可以類似做,想了想沒啥反例。
然後想了一堆不知道什麼垃圾之後得到了一個初步想法,即現在有一些鏈,你要儘可能多的兩兩配對使得配對的長度和大於等於二分的值,做法是已經大於等於二分的值的鏈不管它,然後從大到小每個都選擇儘可能小的配對。
這樣沒有過大樣例及對拍,對拍了小資料發現這樣並不能保證最後留下來的是最大的,結合資料範圍意識到還需要一個二分,才過了大樣例和對拍。
做完了。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define gc getchar()
using namespace std;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const int N=50010;
struct edges{
int to,pre,wgt;
}e[N<<1];int h[N],etop,a[N],b[N],c[N];
inline int add_edge(int u,int v,int w)
{ return e[++etop].to=v,e[etop].pre=h[u],e[etop].wgt=w,h[u]=etop; }
namespace subtask_std{
int sv[N],res[N],vis[N];
inline int check(int cnt,int bp,int v)
{
rep (i,1,cnt) vis[i]=0;if(bp) vis[bp]=1;int mxans=0;
for(int i=cnt,j=1;i;i--)
{
if(vis[i]) continue;while(j<i&&(vis[j]||sv[j]+sv[i]<v)) j++;
if(j<i&&!vis[j]&&sv[j]+sv[i]>=v) vis[i]=vis[j]=1,mxans++,j++;
}
return mxans;
}
int dfs(int x,int fa,int v)
{
int cnt=0,ans=0;
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa) ans+=dfs(y,x,v);
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa) sv[++cnt]=res[y]+e[i].wgt;
res[x]=0;if(!cnt) return ans;
sort(sv+1,sv+cnt+1);
while(cnt&&sv[cnt]>=v) ans++,cnt--;
int mxans=check(cnt,0,v),L=1,R=cnt,mid=(L+R)>>1;
while(L<=R)
{
if(check(cnt,mid,v)==mxans) L=mid+1;
else R=mid-1;mid=(L+R)>>1;
}
return res[x]=sv[R],ans+=mxans;
}
inline int acceptable_solution(int n,int m)
{
memset(h,0,sizeof(int)*(n+1)),etop=0;
rep(i,1,n-1) add_edge(a[i],b[i],c[i]),add_edge(b[i],a[i],c[i]);
int L=1,R=0;rep(i,1,n-1) R+=c[i];
for(int mid=(L+R)>>1;L<=R;mid=(L+R)>>1)
if(dfs(1,0,mid)>=m) L=mid+1;
else R=mid-1;
return !printf("%d\n",R);
}
}
int main()
{
int n=inn(),m=inn();
rep(i,1,n-1) a[i]=inn(),b[i]=inn(),c[i]=inn();
return subtask_std::acceptable_solution(n,m);
}