【BZOJ1196】[HNOI2006]公路修建问题【二分】【并查集】

【题目链接】

二分最大边权,把不大于mid的边做个生成树。

因为只要保证最大值不超过mid即可,具体边权、边权总和无所谓的。

/* Telekinetic Forest Guard */
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 10005, maxm = 20005;

int n, m, k, fa[maxn];

struct _edge {
	int u, v, w, c;
} g[maxm << 1];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

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

inline bool check(int mid) {
	for(int i = 1; i <= n; i++) fa[i] = i;
	int cnt = 0;
	for(int i = 1; i <= m; i++) if(g[i].w <= mid) {
		int u = find(g[i].u), v = find(g[i].v);
		if(u != v) fa[u] = v, cnt++;
	}
	if(cnt < k) return 0;
	for(int i = 1; i <= m; i++) if(g[i].c <= mid) {
		int u = find(g[i].u), v = find(g[i].v);
		if(u != v) fa[u] = v, cnt++;
	}
	return cnt == n - 1;
}
	
int main() {
	n = iread(); k = iread(); m = iread(); m--;
	int l = 1, r = 1;
	for(int i = 1; i <= m; i++) {
		int u = iread(), v = iread(), w = iread(), c = iread();
		g[i] = (_edge){u, v, w, c};
		r = max(r, max(w, c));
	}
	while(l <= r) {
		int mid = l + r >> 1;
		if(check(mid)) r = mid - 1;
		else l = mid + 1;
	}
	printf("%d\n", l);
	return 0;
}
    原文作者:道路修建问题
    原文地址: https://blog.csdn.net/BraketBN/article/details/51461943
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞