BZOJ 2654tree

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2654tree相关的知识,希望对你有一定的参考价值。

Description

  给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
  题目保证有解。

 

Input

  第一行V,E,need分别表示点数,边数和需要的白色边数。
  接下来E行
  每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)。

 

Output

  一行表示所求生成树的边权和。

 

Sample Input

2 2 1
0 1 1 1
0 1 2 0


Sample Output

2

HINT

 

数据规模和约定

  0:V<=10

  1,2,3:V<=15

  0,..,19:V<=50000,E<=100000

  所有数据边权为[1,100]中的正整数。

orz 王梦迪大神
技术分享
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int N=50010;
 5 struct ee{int x,y,w,c;}e[N*2];
 6 int fa[N];
 7 int ans,E,V,need,tot;
 8 int root(int x){
 9     if(fa[x]==x) return x;
10     fa[x]=root(fa[x]);return fa[x];
11 }
12  
13 bool cmp(ee a,ee b){
14     if(a.w==b.w) return a.c<b.c;
15     return a.w<b.w;
16 }
17  
18 int kls(){
19     tot=0;int sum=0,num=0;
20     for(int i=0;i<V;i++) fa[i]=i;
21     for(int i=1;i<=E&&sum<V-1;i++){
22         int xx=root(e[i].x),yy=root(e[i].y);
23         if(xx!=yy) fa[xx]=yy,sum++,tot+=e[i].w,num+=(e[i].c==0);
24     }
25     return num;
26 }
27 int main(){
28     scanf("%d%d%d",&V,&E,&need);
29     int s,t,w,c;
30     for (int i=1;i<=E;i++){
31         scanf("%d%d%d%d",&s,&t,&w,&c);
32         e[i].x=s;e[i].y=t;e[i].w=w;e[i].c=c;
33     }
34     int l=-100,r=100;
35     while(l<=r){
36         int mid=(l+r)>>1;
37         for (int i=1;i<=E;i++) if(e[i].c==0)e[i].w+=mid;
38         sort(e+1,e+1+E,cmp);
39         int h=kls();
40         if(h>=need) ans=(tot-need*mid),l=mid+1;else r=mid-1;
41     //ans这里要注意一下,1wa
42         for (int i=1;i<=E;i++) if(e[i].c==0)e[i].w-=mid;
43     }
44     printf("%d",ans);
45 }

 

以上是关于BZOJ 2654tree的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2654 tree

BZOJ 2654tree

@bzoj - 2654@ tree

bzoj2654 tree

二分+最小生成树bzoj2654: tree

BZOJ2654 - tree