bzoj3624 [Apio2008]免费道路

Description

这里写图片描述

Input

这里写图片描述

OutPut

这里写图片描述

Sample Input

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

Sample Output

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

Solution

失踪人口回归。
题目大意:求图一棵生成树,使得这棵树里恰好有 (k) 条特殊边。
两遍 (kruskal) ,第一遍优先加入非特殊边,预处理出有哪些边是非选不可的。第二遍先加入 (k) 条特殊边,再加入非特殊边。判断 (no) (solution)时细节较多,详见代码。

#include<bits/stdc++.h>
using namespace std;

#define N 200001
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drp(i, a, b) for (int i = a; i >= b; i--)
#define No { puts("no solution"); return 0; }

inline int read() {
	int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
	while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
}

inline void write(int x) {
	if (!x) { putchar('0'); return; } if (x < 0) putchar('-'), x = -x;
	char buf[30] = ""; int top = 0; while (x) buf[++top] = x % 10 + '0', x /= 10; while (top) putchar(buf[top--]);
}

int n, m, K;
struct edgeType {
	int u, v, w; bool chos;
	void outPut() { if (!chos) return; write(u), putchar(' '), write(v), putchar(' '), write(w), puts(""); }
}eg[N];
bool cmp(const edgeType& a, const edgeType& b) { return a.w > b.w; }

int fa[20001];
int find(int x) { return fa[x] ? fa[x] = find(fa[x]) : x; }

int main() {
	n = read(), m = read(), K = read(); 
	rep(i, 1, m) eg[i].u = read(), eg[i].v = read(), eg[i].w = read(); sort(eg + 1, eg + 1 + m, cmp);
	int spCnt = 0;
	rep(i, 1, m) {
		int x = find(eg[i].u), y = find(eg[i].v); if (!(x ^ y)) continue;
		fa[x] = y; if (!eg[i].w) eg[i].chos = 1, spCnt++;
	}
	if (spCnt > K) No;
	memset(fa, 0, sizeof fa); int cnt = 0; spCnt = 0;
	rep(i, 1, m) if (eg[i].chos) { fa[find(eg[i].u)] = find(eg[i].v); cnt++; spCnt++; continue; }
	drp(i, m, 1) {
		if (cnt == n - 1) break; if (eg[i].w && spCnt != K) No;
		int x = find(eg[i].u), y = find(eg[i].v); if (!(x ^ y) || eg[i].chos) continue;
		if (!eg[i].w && spCnt < K) fa[x] = y, eg[i].chos = 1, spCnt++, cnt++;
		else if (eg[i].w) fa[x] = y, eg[i].chos = 1, cnt++;
	}
	if (cnt ^ (n - 1)) No;
	rep(i, 1, m) eg[i].outPut();
	return 0;
}
原文地址:https://www.cnblogs.com/aziint/p/8416246.html