BZOJ 2654: tree( 二分 + MST )

我们给白色的边增加权值 , 则选到的白色边就会变多 , 因此可以二分一下.

不过这道题有点小坑...

-------------------------------------------------------------------------------------------

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<iostream>

#define rep( i , n ) for( int i = 0 ; i < n ; ++i )

#define clr( x , c ) memset( x , c , sizeof( x ) )

using namespace std;

const int maxn = 50000 + 5;

const int maxm = 100000 + 5;

int add , n , m , need;

int p[ maxn ];

int find( int x ) {

return p[ x ] == x ? x : p[ x ] = find( p[ x ] );

}

void UF_clear() {

rep( i , n ) p[ i ] = i;

}

struct edge {

int u , v , d , s;

void Read() {

scanf( "%d%d%d%d" , &u , &v , &d , &s );

s ^= 1;

}

bool operator < ( const edge &e ) const {

return d < e.d || ( d == e.d && s > e.s );

}

};

edge E[ maxm ];

struct node {

int L , R , w;

};

int kruskal() {

int ans = 0 , cnt = 0;

UF_clear();

rep( i , m ) {

edge &e = E[ i ];

if( e.s ) e.d += add;

}

sort( E , E + m );

rep( i , m ) {

edge &e = E[ i ];

int a = find( e.u ) , b = find( e.v );

if( a != b ) {

p[ a ] = b;

ans += e.d;

if( e.s ) cnt++;

}

}

rep( i , m ) {

edge &e = E[ i ];

if( e.s ) e.d -= add;

}

return cnt >= need ? ans : -1;

}

int main() {

freopen( "test.in" , "r" , stdin );

cin >> n >> m >> need;

rep( i , m )

E[ i ].Read();

int ans;

int L = -300 , R = 300;

while( L <= R ) {

add = ( L + R ) >> 1;

int x = kruskal();

if( x != -1 ) {

ans = x - need * add;

L = add + 1;

} else

R = add - 1;

}

cout << ans << "\n";

return 0;

}

-------------------------------------------------------------------------------------------

2654: tree

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

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

Source

时间: 2024-10-18 00:51:06

BZOJ 2654: tree( 二分 + MST )的相关文章

BZOJ 2654 &amp; 玄学二分+MST

题意: 给一张图,边带权且带颜色黑白,求出一棵至少包含k条白边的MST SOL: 正常人都想优先加黑边或者是白边,我也是这么想的...你看先用白边搞一棵k条边的MST...然后维护比较黑边跟白边像堆一样慢慢往里面加...不过讲课的时候跟原题有点出入...这里只有k条边好像比较难维护... 正解也非常巧妙...首先如果有一棵MST,他所含白边数量多于k,那么我们如果可以适当增加白边的边权那么我们就可以减少它的边而且达到最优....想想很有道理你让我证明那有点日了狗了... 然后我们就二分白边的增加

BZOJ 2654 tree 二分+最小生成树

题目大意 给出一些边,每个边有一个边权和颜色.现在要求出最小边权有need个白边的生成树.输出这个边权. 思路 在白边上加一个权值,这样就可以人为的改变白边出现在最小生成树.这个东西显然可以二分.之后取一下最小值就可以了. CODE #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #def

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

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2654 [题目大意] 给你一个无向带权连通图,每条边是黑色或白色. 让你求一棵最小权的恰好有need条白色边的生成树.题目保证有解. [题解] 我们发现对于选中的边白色是从小到大的,黑色也是从小到大的, 因此我们对所有的白色边加一个权值,那么排序后做mst选取的白色边数量增减性单调, 对于增加的权值进行二分,验证能否满足要求即可. [代码] #include <cstdio> #in

bzoj 2654 tree - 二分法 - 最小生成树

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

BZOJ 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

(MST+二分) bzoj 2654

2654: tree Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 515  Solved: 195[Submit][Status][Discuss] Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示点数,边数和需要的白色边数. 接下来E行 每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑

【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

BZOJ 3754 Tree之最小方差树 MST

题目大意:求一个图的最小标准差生成树. 思路:毫无思路,之后看了题解.居然是一个很厉害的暴力. 一个很关键的地方:枚举平均值,然后根据(a - ave(a))^2将边排序,做最小生成树.所有的标准差最小值就是答案. 但是这是为什么?如果当前枚举的ave(a)并不是选取的边的平均值怎么办? 那么就一定有一个你会枚举到的ave(a)计算之后的标准差要比现在小. 这样基本就可以说明这个做法的正确性了.但是需要枚举的范围很大,虽然c只有100,但是按照多大枚举呢.很显然是按照EPS = 1.0 / (m

【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