CF891C Envy

CF891C Envy
Q3.2.2.4. MST 边集询问

最小生成树(森林)中相同权值的边数量不变
先求加入第 i 条边后两个点所在连通块
对于每一个权值: 用并查集判断所在连通块是否有环(有则无解)

点击查看代码
 
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <utility>
#include <array>
#include <vector>

using namespace std;

const int N = 5e5 + 5, M = 1e6 + 5;

int n, m;
struct Edges {
	int a, b, w, id; // 端点1, 端点2, 权值, 编号
	int fa, fb; // a 所在连通块, b 所在连通块
} edges[M];
int father[N];
int pos[N]; // 编号为 i 的边的下标

int find(int x) {
	if(x == father[x]) return x;
	return father[x] = find(father[x]);
}

bool cmp(const Edges &a, const Edges &b) {
	return a.w < b.w;
}

int main() {
	scanf("%d%d", &n, &m);
	for(int i = 1, a, b, c; i <= m; i ++) {
		scanf("%d%d%d", &a, &b, &c);
		edges[i] = {a, b, c, i, 0, 0};
	}
	sort(edges + 1, edges + m + 1, cmp);
	for(int i = 1; i <= n; i ++) father[i] = i;
	for(int i = 1; i <= m; ) {
		int j = i;
		while(edges[j].w == edges[i].w) {
			edges[j].fa = find(edges[j].a); // 所在连通块
			edges[j].fb = find(edges[j].b); // 所在连通块
			j ++;
		}
		while(i < j) {
			father[find(edges[i].a)] = find(edges[i].b); // 合并
			i ++;
		}
	}
	for(int i = 1; i <= m; i ++) pos[edges[i].id] = i;
	int q;
	scanf("%d", &q);
	for(int i = 1; i <= n; i ++) father[i] = i;
	while(q --) {
		int edges_cnt;
		scanf("%d", &edges_cnt);
		vector<int> query;
		bool ok = true;
		for(int i = 1, x; i <= edges_cnt; i ++) {
			scanf("%d", &x);
			x = pos[x];
			query.push_back(x);
		}
		sort(query.begin(), query.end(), [&](const int &x, const int &y) {
			return edges[x].w < edges[y].w;
		});
		for(int i = 0, sz = query.size(); i < sz && ok; ) {
			int j = i; // [i, j)
			while(j < sz && edges[query[i]].w == edges[query[j]].w) {
				int fa = find(edges[query[j]].fa), fb = find(edges[query[j]].fb); // 环!
				if(fa == fb) {
					ok = false;
					break;
				}
				father[fa] = fb; // 合并
				j ++;
			}
			while(i < j) {
				father[edges[query[i]].fa] = edges[query[i]].fa; // 恢复
				father[edges[query[i]].fb] = edges[query[i]].fb; // 恢复
				i ++;
			}
		}
		putchar(ok ? '1' : '0');
	}
	return 0;
}
posted @ 2022-09-28 14:06  azzc  阅读(27)  评论(0编辑  收藏  举报