/* *State: HDU4263 453MS 3784K 1452 B C++ *题目大意: * 有一个无向无权图,只含有红边跟蓝边,判断是否它有一棵 * 最小生成树含有确定的k条蓝边。 *解题思路: * 求一遍含蓝边最多的最小生成树,其中蓝边数为Max, 求一遍 * 含蓝边最少的最小生成树,其中蓝边数为Min.如果k值处于[Min, Max] * 这个闭区间里面,那么该图含有题目要求的MST. * 为什么是这样呢:因为这两棵极端的MST合并在一起只有两种 * 情况,1、就是只含有蓝边的环,这时候删掉一条蓝边,2、另一种情况 * 是含有红边跟蓝边的环,这时候每删去一条红边,那么当前的MST的 * 蓝边数就上升1,所以MST含有蓝边数是在[Min, Max]这个区间中。 */
View Code
#include <iostream> #include <algorithm> using namespace std; const int MAXE = 1000005; const int MAXN = 1005; typedef struct _edge { int u, v, w; }E; E edge[MAXE]; int fa[MAXN]; int findSet(int x) { if(x != fa[x]) fa[x] = findSet(fa[x]); return fa[x]; } bool Union(int x, int y) { int a = findSet(x); int b = findSet(y); if(a == b) return false; fa[b] = a; return true; } void initSet() { for(int i = 0; i < MAXN; i++) fa[i] = i; } bool cmp1(const E &a, const E &b) { return a.w < b.w; } bool cmp2(const E &a, const E &b) { return a.w > b.w; } int main(void) { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n, m, k; while(scanf("%d %d %d", &n, &m, &k), n || m || k) { int u, v, w; char op[5]; for(int i = 0; i < m; i++) { scanf("%s %d %d", op, &u, &v); if(op[0] == 'B') { edge[i].u = u, edge[i].v = v; edge[i].w = 1; } else { edge[i].u = u, edge[i].v = v; edge[i].w = 0; } } initSet(); int Min = 0, Max = 0; sort(edge, edge + m, cmp1); for(int i = 0; i < m; i++) { if(Union(edge[i].u, edge[i].v) && edge[i].w) Min++; } initSet(); sort(edge, edge + m, cmp2); for(int i = 0; i < m; i++) { if(Union(edge[i].u, edge[i].v) && edge[i].w) Max++; } if(k >= Min && k <= Max) printf("1\n"); else printf("0\n"); } return 0; }