hdu4253 二分+MST (经典模型)

n个点,m条边,边分为A,B两类,要构造一棵最小生成树,且树中A边数量为k。

 

我们可以通过给所有A边加上权值dx来控制树中A边的数量。显然,当dx增大,A边数量kk会减少。

二分dx,

当kk>=k,增大dx(即l=mid+1),同时更新ans=sum(mst)-mid*k;

 当kk<k,减小dx(即r=mid-1)。

 

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 struct node
  6 {
  7     int u,v,w;
  8 }ey[110000],el[110000];
  9 int n,m,k,numey,numel,sset[110000],sum;
 10 const int mmax=1<<30;
 11 int ffind(int x)
 12 {
 13     if(sset[x]==x) return x;
 14     int fa=sset[x];
 15     sset[x]=ffind(fa);
 16     return sset[x];
 17 }
 18 void mmerge(int a,int b)
 19 {
 20     int aa=ffind(a);
 21     int bb=ffind(b);
 22     if(aa!=bb)
 23         sset[aa]=bb;
 24 }
 25 bool cmp(node x1,node y1)
 26 {
 27     return x1.w<y1.w;
 28 }
 29 int kruscal(int dx)
 30 {
 31     int i;
 32     sum=0;
 33     for(i=0;i<=n;i++)
 34         sset[i]=i;
 35     int kk=0,posey=0,posel=0,num=0;
 36     while(posey<numey||posel<numel)
 37     {
 38         int from,to;
 39         if(ey[posey].w+dx<=el[posel].w)
 40         {
 41             from=ffind(ey[posey].u);
 42             to=ffind(ey[posey].v);
 43             if(from!=to)
 44             {
 45                 mmerge(ey[posey].u,ey[posey].v);
 46                 sum+=(ey[posey].w+dx);
 47                 kk++;
 48                 num++;
 49             }
 50             posey++;
 51         }
 52         else
 53         {
 54             from=ffind(el[posel].u);
 55             to=ffind(el[posel].v);
 56             if(from!=to)
 57             {
 58                 mmerge(el[posel].u,el[posel].v);
 59                 sum+=el[posel].w;
 60                 num++;
 61             }
 62             posel++;
 63         }
 64         if(num==n-1) break;
 65     }
 66     if(kk>=k) return 1;
 67     else return 0;
 68 }
 69 int main()
 70 {
 71     int i,casnum=0;
 72     while(scanf("%d%d%d",&n,&m,&k)!=EOF)
 73     {
 74         numey=numel=0;
 75         for(i=0;i<m;i++)
 76         {
 77             int a,b,c,tmp;
 78             scanf("%d%d%d%d",&a,&b,&c,&tmp);
 79             if(tmp==0)
 80             {
 81                 ey[numey].u=a;
 82                 ey[numey].v=b;
 83                 ey[numey++].w=c;
 84             }
 85             else
 86             {
 87                 el[numel].u=a;
 88                 el[numel].v=b;
 89                 el[numel++].w=c;
 90             }
 91         }
 92         sort(ey,ey+numey,cmp);
 93         sort(el,el+numel,cmp);
 94         ey[numey].w=el[numel].w=mmax;
 95         int l=-100,r=100,mid,ans=0;
 96         while(l<=r)
 97         {
 98             mid=(l+r)/2;
 99             if(kruscal(mid))
100             {
101                 l=mid+1;
102                 ans=sum-mid*k;
103             }
104             else r=mid-1;
105         }
106         printf("Case %d: %d\n",++casnum,ans);
107     }
108     return 0;
109 }

 

posted @ 2016-04-03 15:41  2014551532  阅读(375)  评论(0编辑  收藏  举报