
我们给白色的边增加权值 , 则选到的白色边就会变多 , 因此可以二分一下.
不过这道题有点小坑... 
-------------------------------------------------------------------------------------------
#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
 
BZOJ 2654: tree( 二分 + MST )
原文:http://www.cnblogs.com/JSZX11556/p/4573693.html