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;
}

浙公网安备 33010602011771号