[bzoj2654]tree 二分+最小生成树

来源:互联网 发布:苹果淘宝下载 编辑:程序博客网 时间:2024/05/17 18:29

2654: tree

Time Limit: 30 Sec  Memory Limit: 512 MB
[Submit][Status][Discuss]

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

就二分再kruskal一下就完了。没做头
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int N = 100005;struct Edge{int u,v,w,c;}e[N];int a[N],u[N],v[N],w[N],c[N],fa[N],n,m,maxn,ans,scnt,cnt,need;int find( int x ){ return fa[x] == x ? x : fa[x] = find(fa[x]); }bool cmp( Edge a, Edge b ){ return a.w == b.w ? a.c < b.c : a.w < b.w; }bool check( int x ){scnt = cnt = 0;for( int i = 1; i <= n; i++ ) fa[i] = i;for( int i = 1; i <= m; i++ ){e[i].u = u[i]; e[i].v = v[i];e[i].w = w[i]; e[i].c = c[i];if( !c[i] ) e[i].w += x;}std::sort( e+1, e+m+1, cmp );for( int i = 1; i <= m; i++ ){int A = find(e[i].u), B = find(e[i].v);if( A != B ){fa[A] = fa[B]; if(!e[i].c) scnt++;cnt += e[i].w;}}return scnt >= need;}int main(){scanf("%d", &n); scanf("%d", &m); scanf("%d", &need);for( int i = 1; i <= m; i++ ) scanf("%d%d%d%d", &u[i], &v[i], &w[i], &c[i]),u[i]++,v[i]++;int l = -105, r = 105;while( l <= r ){int mid = (l+r)>>1;if( check(mid) ) l = mid+1, ans = cnt-need*mid;else r = mid-1;}printf("%d", ans);return 0;}


原创粉丝点击