首页 > 代码库 > 【BZOJ 2654】 MST

【BZOJ 2654】 MST

2654: tree

Description

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

Input

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

Output

一行表示所求生成树的边权和。
V<=50000,E<=100000,所有数据边权为[1,100]中的正整数。

Sample Input

2 2 1
0 1 1 1
0 1 2 0

Sample Output

2

HINT

原数据出错,现已更新 by liutian,但未重测---2016.6.24

Source

 

 

 

【分析】

  嗯?我想不到的题。。如果不断给所有白色边加上同一个值,跑MST(边权相同先选白色边),那么选取的白色边的数量显然是不降的,就这样,最后减掉need*add就好了。

 

技术分享
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 #define Maxn 50010
 8 #define Maxm 100010
 9 #define INF 0x7fffffff
10 
11 int n,m,k;
12 
13 int mymin(int x,int y) {return x<y?x:y;}
14 
15 struct node
16 {
17     int x,y,c,cc,p,next;
18 }t[Maxm*2];
19 int first[Maxn],len;
20 
21 void ins(int x,int y,int c,int p)
22 {
23     t[++len].x=x;t[len].y=y;t[len].cc=t[len].c=c;t[len].p=p;
24     t[len].next=first[x];first[x]=len;
25 }
26 
27 bool cmp(node x,node y) 
28 {
29     if(x.c==y.c) return x.p<y.p;
30     return x.c<y.c;
31 }
32 
33 int fa[Maxn];
34 int ffa(int x)
35 {
36     if(fa[x]!=x) fa[x]=ffa(fa[x]);
37     return fa[x];
38 }
39 
40 int tot,now;
41 void check(int x)
42 {
43     tot=0;now=0;
44     for(int i=1;i<=n;i++) fa[i]=i;
45     for(int i=1;i<=len;i++) if(!t[i].p) t[i].c=t[i].cc+x;
46     sort(t+1,t+1+len,cmp);
47     for(int i=1;i<=len;i++)
48     {
49         int x=t[i].x,y=t[i].y;
50         if(ffa(x)!=ffa(y))
51         {
52             fa[ffa(x)]=ffa(y);
53             if(!t[i].p) tot++;
54             now+=t[i].c;
55         }
56     }
57 }
58 
59 int ffind(int l,int r)
60 {
61     int ans=INF;
62     while(l<=r)
63     {
64         int mid=(l+r)>>1;check(mid);
65         if(tot>=k) ans=now-k*mid,l=mid+1;
66         else r=mid-1;
67     }
68     return ans;
69 }
70 
71 int main()
72 {
73     scanf("%d%d%d",&n,&m,&k);
74     len=0;
75     memset(first,0,sizeof(first));
76     int cnt=0;
77     for(int i=1;i<=m;i++)
78     {
79         int x,y,c,p;
80         scanf("%d%d%d%d",&x,&y,&c,&p);
81         x++;y++;
82         if(p==0) cnt++;
83         ins(x,y,c,p);ins(y,x,c,p);
84     }
85     int ans=ffind(-100,100);
86     if(ans==INF) ans=0;
87     printf("%d\n",ans);
88     return 0;
89 }
View Code

 

 

2017-03-08 21:26:50

【BZOJ 2654】 MST