hdu4263 Red/Blue Spanning Tree

思路:有两种没有边权但是有染色的边,现在问时候能够形成确切的含有K条Blue边的生成树。直接找是不现实的,但是我们可以看至少和之多需要多少条就行了,只要K在这两个值之间就行了。因为从最少的Blue边开始,用blue边替换RED边,这样是可以形成环的,所以替换是可行的,这样就可以一步一步替换成含有k条blue边的生成树。

// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
// #define DEBUG
#ifdef DEBUG
#define debug(...) printf( __VA_ARGS__ )
#else
#define debug(...)
#endif
#define CLR(x) memset(x, 0,sizeof x)
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
template<class T> inline T Get_Max(const T&a,const T&b){return a < b?b:a;}
template<class T> inline T Get_Min(const T&a,const T&b){return a < b?a:b;}
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1010;
int n,m,k;
struct Edge{
	int u, v, w;
	Edge(){}
	Edge(int _u,int _v,int _w):u(_u),v(_v),w(_w){}
	bool operator < (const Edge& rhs)const{
		return w < rhs.w;
	}
}E[maxn*10000];
int F[maxn];
int Find(int x){
	if (F[x]==-1) return x;
	return F[x] = Find(F[x]);
}
int cnt;
int solve(){
	memset(F, -1,sizeof F);
	int ans = 0;
	int sum = 0;
	sort(E,E+cnt);
	for (int i = 0;i < cnt;++i){
		int t1 = Find(E[i].u);
		int t2 = Find(E[i].v);
		if (t1 != t2){
			F[t1] = t2;
			sum += E[i].w;
			ans++;
		}
		if (ans==n-1)return sum;
	}
	if (ans==n-1) return sum;
	return INF;
}
int main()
{	
	// freopen("in.txt","r",stdin);
	// freopen("out.txt","w",stdout);
	while(scanf("%d%d%d",&n,&m,&k) != EOF){
		if (n==0&&m==0&&k==0)break;
		cnt=0;
		char op[10];
		int x,y;
		for (int i = 0;i < m;++i){
			scanf("%s",op);
			scanf("%d%d",&x,&y);
			E[cnt++] = Edge(x,y,op[0]=='B'?0:1);
		}
		int ans = solve();
		for (int i = 0;i < cnt;++i){
			E[i].w = 1 - E[i].w;
		}
		int sum = solve();
		if (ans != INF){
			ans = (n-1) - ans;
			if (sum <= k && k <= ans){
				cout << 1 << endl;
				continue;
			}
		}
		cout << 0 << endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值