[BZOJ3624][Apio2008]免费道路

[BZOJ3624][Apio2008]免费道路

试题描述

输入

输出

输入示例

5 7 2
1 3 0
4 5 1
3 2 0
5 3 1
4 3 0
1 2 1
4 2 1

输出示例

3 2 0
4 3 0
5 3 1
1 2 1

数据规模及约定

见“输入”。

题解

第一步,先尽量加入 c = 1 的边,若未形成一个连通块,则得到必须加入的 c = 0 的边。

第二步,加入那些必须加入的 c = 0 的边,尽量加入 c = 0 的边直到这种边数量达到 k,再加入 c = 1 的边直到形成一棵树。

最后判一判 no solution 的情况。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std;

const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
	if(Head == Tail) {
		int l = fread(buffer, 1, BufferSize, stdin);
		Tail = (Head = buffer) + l;
	}
	return *Head++;
}
int read() {
	int x = 0, f = 1; char c = Getchar();
	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
	return x * f;
}

#define maxn 20010
#define maxm 100010
int n, m, k;
struct Edge {
	int u, v;
	bool c, has;
	void get() {
		u = read(); v = read(); c = read(); has = 0;
		return ;
	}
} es[maxm];

int fa[maxn];
void init() { for(int i = 1; i <= n; i++) fa[i] = i; return ; }
int findset(int x) { return x == fa[x] ? x : fa[x] = findset(fa[x]); }

int main() {
	n = read(); m = read(); k = read();
	for(int i = 1; i <= m; i++) es[i].get();
	
	init();
	for(int i = 1; i <= m; i++) if(es[i].c) {
		int u = findset(es[i].u), v = findset(es[i].v);
		if(u != v) fa[v] = u;
	}
	for(int i = 1; i <= m; i++) if(!es[i].c) {
		int u = findset(es[i].u), v = findset(es[i].v);
		if(u != v) fa[v] = u, es[i].has = 1;
	}
	int cnt = 0;
	init();
	for(int i = 1; i <= m; i++) if(es[i].has) fa[findset(es[i].v)] = findset(es[i].u), cnt++;
	for(int i = 1; i <= m && cnt < k; i++) if(!es[i].c) {
		int u = findset(es[i].u), v = findset(es[i].v);
		if(u != v) fa[v] = u, es[i].has = 1, cnt++;
	}
	for(int i = 1; i <= m; i++) if(es[i].c) {
		int u = findset(es[i].u), v = findset(es[i].v);
		if(u != v) fa[v] = u, es[i].has = 1;
	}
	
	if(cnt != k) puts("no solution");
	else for(int i = 1; i <= m; i++) if(es[i].has) printf("%d %d %d\n", es[i].u, es[i].v, es[i].c);
	
	return 0;
}

 

posted @ 2016-06-29 12:52  xjr01  阅读(184)  评论(0编辑  收藏  举报