给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有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


  显然是MST,但是在Kruskal的过程中我们无法控制白边的数量。如果考虑修改边值,可以发现如果给白边的边权都加上一个delta,那么白边的数量随着delta的增大而减小。所以可以二分它去控制白边的数量。

Code

 /**
* bzoj
* Problem#2654
* Accepted
* Time:1892ms
* Memory:3052k
*/
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<vector>
#include<stack>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean;
const signed int inf = (signed)((1u << ) - );
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b)
#define max3(a, b, c) max(a, max(b, c))
#define min3(a, b, c) min(a, min(b, c))
template<typename T>
inline boolean readInteger(T& u){
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-' && x != -);
if(x == -) {
ungetc(x, stdin);
return false;
}
if(x == '-'){
x = getchar();
aFlag = -;
}
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
u *= aFlag;
return true;
} typedef class union_found{
public:
int *f;
union_found():f(NULL) {}
union_found(int points) {
f = new int[(const int)(points + )];
clear(points);
}
int find(int x) {
if(f[x] != x) return f[x] = find(f[x]);
return f[x];
}
void unit(int fa, int so) {
int ffa = find(fa);
int fso = find(so);
f[fso] = ffa;
}
boolean connected(int a, int b) {
return find(a) == find(b);
}
void clear(int points) {
for(int i = ; i <= points; i++)
f[i] = i;
}
}union_found; int delta = ; typedef class Edge {
public:
int from;
int end;
int val;
boolean col; inline int getVal() const {
if(col) return val + delta;
return val;
}
}Edge; boolean operator < (const Edge& a, const Edge& b) {
return a.getVal() < b.getVal();
} int n, m, lim;
union_found uf;
Edge* edge; inline void init() {
readInteger(n);
readInteger(m);
readInteger(lim);
uf = union_found(n);
edge = new Edge[(const int)(m + )];
for(int i = ; i < m; i++) {
readInteger(edge[i].from);
readInteger(edge[i].end);
readInteger(edge[i].val);
readInteger(edge[i].col);
edge[i].col ^= ;
}
} int res = ;
int kruskal(int mid) {
delta = mid;
res = ;
uf.clear(n);
sort(edge, edge + m);
int fw = , fin = ;
for(int i = ; i < m; i++) {
if(!uf.connected(edge[i].from, edge[i].end)) {
uf.unit(edge[i].from, edge[i].end);
fw += edge[i].col, fin ++, res += edge[i].val;
}
}
return fw;
} inline void solve() {
int l = -, r = , c;
while(l <= r) {
int mid = (l + r) >> ;
if((c = kruskal(mid)) < lim) r = mid - ;
else if(c > lim) l = mid + ;
else break;
}
printf("%d\n", res);
} int main() {
init();
solve();
return ;
}

bzoj 2654 tree - 二分法 - 最小生成树的更多相关文章

  1. BZOJ 2654: tree(二分 最小生成树)

    Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 2901  Solved: 1196[Submit][Status][Discuss] Descript ...

  2. BZOJ 2654: tree( 二分 + MST )

    我们给白色的边增加权值 , 则选到的白色边就会变多 , 因此可以二分一下. 不过这道题有点小坑... ------------------------------------------------- ...

  3. BZOJ 2654: tree Kruskal+二分答案

    2654: tree Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1863  Solved: 736[Submit][Status][Discuss ...

  4. BZOJ 2654: tree

    Description \(n\) 个点, \(m\) 条边,边有权值和黑/白色,求含有 \(need\) 个白边的生成树. Sol 二分+Kruskal. 将每条白边都加上一个权值,然后跑最小生成树 ...

  5. [BZOJ 2654]tree(陈立杰)

    Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示点数,边数和需要的白色 ...

  6. hdu 4253 Two Famous Companies BZOJ 2654 tree

    [题意]:给出n个点,m条边,边分为两种,一种是A公司的,一种是B公司的.边上有权值,问用n-1条边把n个点连起来的最小费用是多少,其中A公司的边刚好有k条.题目保证有解. 思路:我们发现,如果我们给 ...

  7. bzoj 2654 tree 二分+kruskal

    tree Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 2739  Solved: 1126[Submit][Status][Discuss] Des ...

  8. BZOJ 2654 tree(二分答案+并查集)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2654 [题目大意] 给你一个无向带权连通图,每条边是黑色或白色. 让你求一棵最小权的恰 ...

  9. bzoj 2212 Tree Rotations

    bzoj 2212 Tree Rotations 考虑一个子树 \(x\) 的左右儿子分别为 \(ls,rs\) .那么子树 \(x\) 内的逆序对数就是 \(ls\) 内的逆序对数,\(rs\) 内 ...

随机推荐

  1. 25个站长必备的SEO优化工具

    搜索引擎抓取内容模拟器 可以模拟蜘蛛抓取指定网页,包括Text.Link.Keywords及Description信息等.http://www.webconfs.com/search-engine-s ...

  2. Shell 和Python的区别。

    shell 应该属于宏语言,顾名思义是系统的壳,方便与系统交互的在以下情况下,不使用shell,因为shell对此无能为力:如:跨平台,较复杂数学操作(如浮点运算,精确运算等),图形化界面 GUI,I ...

  3. property:get、set

    property属性:自动调用get.set方法 每次调用隐藏的数据,都用get和set方法写的字符太长,就用property解决. 方法一:使用property()函数升级get.set方法   源 ...

  4. keepalived的log

    vrrp_script chk_http_port { script "</dev/tcp/127.0.0.1/8088" interval 1 weight -2 } ke ...

  5. 006-springboot2.0.4 配置log4j2,以及打印mybatis的sql

    一.pom配置 普通项目 <!-- log4j2 --> <dependency> <groupId>org.apache.logging.log4j</gr ...

  6. U盘安装win10操作系统

    https://www.zhihu.com/question/39207359   1:进入微软官方网站,点击立即下载工具,下载完成mediacreationtool,双击打开,接受协议  https ...

  7. springboot中的日志配置

    日志方式:每天日志存放在一个文件中,info和warn日志存放一个文件,error存放一个文件 创建文件 logback-spring.xml <?xml version="1.0&q ...

  8. 什么时候block 是放在全局区里面的?

    When a Block literal is written where there are global variables When the syntax in a Block literal ...

  9. jmeter 测试websocket接口(二)

    1.到https://github.com/maciejzaleski/JMeter-WebSocketSampler下载Jmeter的WebSocket协议的支持插件:JMeterWebSocket ...

  10. 一个新人对HTML内JavaScript的理解

    首先是对于JavaScript(以后简称JS)的定义: ① JS他是一个脚本语言,有点类似于外部插件,需要插入引用才会有效 ② 他需要一个宿主文件,就是他插入到谁里面进行运算,谁就是这个JS的宿主文件 ...