1. 程式人生 > >NOIP2018 Day1 T3 賽道修建 - 二分套二分 - dp - 貪心

NOIP2018 Day1 T3 賽道修建 - 二分套二分 - dp - 貪心

場上心路歷程:
首先這顯然好像是個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); }