【带权二分】bzoj2654 tree

 注意二分初始值

https://www.cnblogs.com/NaVi-Awson/p/7252243.html

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=50000+5,M=100000+5;
int n,m,need;
 
struct edge{int x,y,z,cor;}a[M]; int mid,sum;
bool cmp(edge p,edge q)
 {if(p.z+p.cor*mid==q.z+q.cor*mid) return p.cor<q.cor;
  return  p.z+p.cor*mid<q.z+q.cor*mid;                               
 }
 
int f[N];
int find(int x)
 {if(f[x]==x) return x;
              return f[x]=find(f[x]);
 }
 
inline bool check()
 {for(int i=1;i<=n;i++)  f[i]=i;
  sort(a+1,a+m+1,cmp);
   
  int cnt=0,link=0; sum=0;
   
  for(int i=1;i<=m;i++)
   {int r1=find(a[i].x),r2=find(a[i].y);
    if(r1==r2) continue;
     
    f[r1]=r2;    link++;
     
    sum+=a[i].z; cnt+=a[i].cor;
    if(link==n-1) break;
   }
  return  cnt>=need;
 } 
int main()
 {
 scanf("%d%d%d",&n,&m,&need);    
         
 for(int i=1;i<=m;i++) 
  {scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].z,&a[i].cor);
   a[i].x++; a[i].y++; a[i].cor=1-a[i].cor;
  }
     
 int l=-105,r=105,ans=0;    
  
 while(l<=r)
  {mid=(l+r)/2;
   if(check()) ans=sum,l=mid+1;
   else                r=mid-1;
  } 
 printf("%d",ans); 
return 0;
 }


 

posted @ 2018-09-21 20:41  YuXiaoze  阅读(95)  评论(0编辑  收藏  举报