【并查集】JZOJ 4223 旅游

题目大意:

有一个n个点m条边的无向图,多次询问有多少对(a,b)满足a到b至少有一条路径满足最大边权小于x

解题思路:

把边按边权排序,从小到大加入图中 用并查集维护

A c c e p t e d   c o d e : Accepted\ code: Accepted code:

#include
#include
#include
#include

using namespace std;

struct Line {
     
	int x, y, w;
}e[100005];

int n, m, q, Q, maxn;
int t[20005], fa[20005];
long long sum[100005];

bool cmp(Line x, Line y) {
     
	return x.w < y.w;
}

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

void count() {
     
	for (int i = 1; i <= m; ++i) {
     
		int x = find(e[i].x);
		int y = find(e[i].y);
		if (x != y) {
     
			sum[e[i].w] += t[x] * t[y] * 2ll;
			t[x] += t[y];
			fa[y] = x;
		}
	}
}

int main() {
     
	scanf("%d", &Q);
	while (Q--) {
     
		memset(sum, 0, sizeof sum), maxn = 0;
		scanf("%d %d %d", &n, &m, &q);
		for (int i = 1; i <= m; ++i)
			scanf("%d %d %d", &e[i].x, &e[i].y, &e[i].w),
			maxn = max(maxn, e[i].w);
		sort(e + 1, e + m + 1, cmp);
		for (int i = 1; i <= n; ++i)
			fa[i] = i, t[i] = 1;
		count();
		for (int i = 1; i <= maxn; ++i) sum[i] += sum[i-1];
		while (q--) {
     
			int x; scanf("%d", &x); printf("%lld\n", x > maxn ? sum[maxn] : sum[x]);
		}
	}
} 

你可能感兴趣的:(模拟赛,并查集,排序)