您的位置:首页 > 其它

BZOJ 2654 tree 详解(最小生成树 kruskal 二分)

2017-07-05 20:33 344 查看

BZOJ 2654 tree

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]中的正整数。

思路:

巧妙,

我们发现,如果考虑权值,那么就没有办法处理黑白,如果考虑黑白,那么又做不到权值的最优。

所以我们冥思苦想如何把黑白区分开,又不能改变权值之间的优劣。于是就有了一个神奇的解法,如果我们给白边增加权值,那么求最小生成树时,由于白边权值增大,所有不容易选白边。

这样一来,我们既没有改变他们权值的顺序,而且白边选的就会少一点,最小生成树有保证了当前状态下的最优解。

记f(x)为给白边增加x权值,求出最小生成树后,白边的数量,又可以发现,f(x)随x增大而减小,所以二分x的值。

可能有人会疑惑,有可能x在[a,b]中都满足白边数目为need,这个时候x与ans(树的大小)之间并没有单调关系,怎么能二分呢?针对这道题,只要我们找到了满足白边数目为need的状态,那么它就是答案。为什么?因为我们的ans只与选了那些边有关,x我们最终是要剪掉的,又因为保证了need条白边,所以剩下的选择都是黑边了,而黑边是不受x影响的,所以只要满足了need,那么就是答案。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lim 1000
#define ll long long
using namespace std;

const int N = 100005;

int n, m, cnt, tot, goal, ans;
int u
, v
, w
, c
, fa
;

struct edge{
int u, v, w, c;
}ed[N<<1];

bool cmp(edge a, edge b){
if(a.w == b.w) return a.c < b.c;//优先白
else return a.w < b.w;
}

int find(int x){
if(x == fa[x]) return x;
else return fa[x] = find(fa[x]);
}

bool check(int x){
tot = cnt = 0;
for(int i=1; i<=n; i++) fa[i] = i;
for(int i=1; i<=m; i++){
ed[i].u = u[i];
ed[i].v = v[i];
ed[i].w = w[i];
ed[i].c = c[i];
if( !c[i] ) ed[i].w += x;
}
sort(ed+1, ed+m+1, cmp);
for(int i=1; i<=m; i++){//kruskal
int p = find(ed[i].u), q = find(ed[i].v);
if(p != q){
fa[p] = q;
tot += ed[i].w;
if( !ed[i].c ) cnt++;
}
}
return cnt >= goal;
}

int main(){
scanf("%d%d%d", &n, &m, &goal);
for(int i=1; i<=m; i++){
scanf("%d%d%d%d", &u[i], &v[i], &w[i], &c[i]);
u[i]++; v[i]++;//更改编号为1开始,方便check
}
int l=-lim, r=lim;
while(l <= r){//二分
int mid = (l + r) >> 1;
if( check(mid) ){
l = mid + 1;
ans = tot - goal * mid;//还原
}
else r = mid - 1;
}
printf("%d", ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: