BZOJ 2654: tree 二分+最小生成树
code:
#include <cstdio> #include <algorithm> #define N 50020 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; struct data { int x,y,z; data(int a=0,int b=0,int c=0) {x=a,y=b,z=c;} bool operator<(const data a) const { return z<a.z; } }b[N<<1],w[N<<1]; int tb,tw,n,f[N],sum; int find(int x) { return f[x]==x?x:f[x]=find(f[x]); } int solve(int mid) { int i,pb=1,pw=1,ans=0; sum=0; for(i=0;i<n;++i) f[i]=i; while(pb<=tb||pw<=tw) { if(pw>tw||(pb<=tb&&b[pb].z<w[pw].z+mid)) { if(find(b[pb].x)!=find(b[pb].y)) { sum+=b[pb].z; f[f[b[pb].x]]=f[b[pb].y]; } ++pb; } else { if(find(w[pw].x)!=find(w[pw].y)) { sum+=w[pw].z; f[f[w[pw].x]]=f[w[pw].y]; ++ans; } ++pw; } } return ans; } int main() { // setIO("input"); int i,j,m,k,x,y,z,p,l=-100,r=100,mid,ans; scanf("%d%d%d",&n,&m,&k); for(i=1;i<=m;++i) { scanf("%d%d%d%d",&x,&y,&z,&p); if(p) b[++tb]=data(x,y,z); else w[++tw]=data(x,y,z); } sort(b+1,b+1+tb); sort(w+1,w+1+tw); while(l<=r) { mid=(l+r)>>1; if(solve(mid)>=k) ans=mid,l=mid+1; else r=mid-1; } solve(ans); printf("%d\n",sum); return 0; }