首页 > 代码库 > bzoj2654 tree
bzoj2654 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
0 1 1 1
0 1 2 0
Sample Output
2
HINT
原数据出错,现已更新 by liutian,但未重测---2016.6.24
正解:二分+$kruskal$。
简直是一道神题啊。。
如果直接$kruskal$求最小生成树,是无法保证白边数量的,那么我们考虑如果改变白边的数量。我们可以把白边全部都加上一个权值,也就是我们二分的值,然后跑最小生成树,同时记录白边数量。当白边数量$>=need$时,$l=mid+1$,否则$r=mid-1$,更新答案就是这棵生成树的权值和减去所有白边的增量。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue>10 #include <stack>11 #include <map>12 #include <set>13 #define inf (1<<30)14 #define N (200010)15 #define il inline16 #define RG register17 #define ll long long18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)19 20 using namespace std;21 22 struct edge{ int u,v,w,c; }g[N];23 24 int fa[N],n,m,ans,need;25 26 il int gi(){27 RG int x=0,q=1; RG char ch=getchar();28 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar();29 if (ch==‘-‘) q=-1,ch=getchar();30 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar();31 return q*x;32 }33 34 il int cmp(const edge &a,const edge &b){35 if (a.w==b.w) return a.c<b.c; return a.w<b.w;36 }37 38 il int find(RG int x){ return fa[x]==x ? x : fa[x]=find(fa[x]); }39 40 il int check(RG int key){41 for (RG int i=1;i<=m;++i) if (!g[i].c) g[i].w+=key;42 sort(g+1,g+m+1,cmp); RG int tt=0,sum=0;43 for (RG int i=1;i<=n;++i) fa[i]=i;44 for (RG int i=1,x,y,k=0;i<=m;++i){45 x=find(g[i].u),y=find(g[i].v);46 if (x!=y) ++k,fa[x]=y,tt+=g[i].c^1,sum+=g[i].w;47 if (k==n-1) break;48 }49 if (tt>=need) ans=sum-tt*key;50 for (RG int i=1;i<=m;++i) if (!g[i].c) g[i].w-=key;51 return tt>=need;52 }53 54 il void find(){55 RG int l=-100,r=100,mid;56 while (l<=r){57 mid=(l+r)>>1;58 if (check(mid)) l=mid+1; else r=mid-1;59 }60 return;61 }62 63 il void work(){64 n=gi(),m=gi(),need=gi();65 for (RG int i=1;i<=m;++i)66 g[i].u=gi()+1,g[i].v=gi()+1,g[i].w=gi(),g[i].c=gi();67 find(); printf("%d\n",ans); return;68 }69 70 int main(){71 File("tree");72 work();73 return 0;74 }
bzoj2654 tree
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。