带扩展域和带边权并查集

P2024 [NOI2001] 食物链

AcWing 240. 食物链(带扩展域 和 带边权 并查集 两种做法)

带拓展域的并查集

并查集

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e4 + 10;
int n, m;
int p[N * 5];

int find(int x) {
	if (p[x] != x) {
		p[x] = find(p[x]);
	}
	return p[x];
}
int cnt;
//带 扩展域 的并查集
signed main() {
	cin >> n >> m;
	for (int i = 1; i < N * 5; i++) p[i] = i;
	for (int i = 1; i <= m; i++) {
		int op, x, y;
		cin >> op >> x >> y;
		if (x > n || y > n) {
			cnt++;
			continue;
		}
		//同类?
		if (op == 1) {
			if (x == y) continue;
			if (find(x) == find(y + N) || find(x + N) == find(y)) {
				cnt++;
				continue;
			}
			p[find(x)] = find(y);
			p[find(x + N)] = find(y + N);
			p[find(x + N * 2)] = find(y + N * 2);
		}
		//吃?
		else {
			if (x == y) {
				cnt++;
				continue;
			}
			if (find(x + N) == find(y) || find(x) == find(y)) {
				cnt++;
				continue;
			}
			p[find(x)] = find(y + N);
			p[find(x + N)] = find(y + N * 2);
			p[find(x + N * 2)] = find(y);
		}
	}
	cout << cnt << '\n';
}
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e5 + 10;
int n, m;
int cnt;
int p[N];
int d[N];
//带边权并查集

int find(int x) {
	if (p[x] != x) {
		int t = find(p[x]);
		d[x] += d[p[x]];
		p[x] = t;
	}
	return p[x];
}

signed main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) p[i] = i;
	int ans = 0;
	for (int i = 1; i <= m; i++) {
		int op, x, y;
		cin >> op >> x >> y;
		if (x > n || y > n) {
			ans++;
			continue;
		}
		int a = find(x), b = find(y);
		if (op == 1) {
			if (a == b && (d[x] - d[y]) % 3) {
				ans++;
			} else if (a != b) {
				p[a] = b;
				d[a] = d[y] - d[x];
			}
		} else {
			if (a == b && (d[x] - d[y] - 1) % 3) {
				ans++;
			} else if (a != b) {
				p[a] = b;
				d[a] = d[y] + 1 - d[x];
			}
		}
	}
	cout << ans << '\n';
}

P1196 [NOI2002] 银河英雄传说

带权并查集模板

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 10;
int n, m;
//father数组,路径,队列长度
int p[N], d[N], si[N];
int find(int x) {
	if (p[x] != x) {
		int t = find(p[x]);
		d[x] += d[p[x]];
		p[x] = t;
	}
	return p[x];
}

signed main() {
	for (int i = 1; i < N; i++) p[i] = i, si[i] = 1;
	int T;
	cin >> T;
	while (T--) {
		char op;
		int x, y;
		cin >> op >> x >> y;
		if (op == 'M') {
			int a = find(x), b = find(y);
//       需要判断,防止size数组重复加
			if (a != b) {
				p[a] = b;
				d[a] = si[b];
				si[b] += si[a];
			}
		} else {
			int a = find(x), b = find(y);
// 			cout << a << ' ' << b << '\n';
// 			cout << d[x] << ' ' << d[y] << '\n';
			if (a != b) cout << -1 << '\n';
			else {
				if (d[x] != d[y])
					cout << abs(d[x] - d[y]) - 1 << '\n';
				else
					cout << 0 << '\n';
			}
		}
	}
}
posted @ 2024-10-12 19:07  ZhangDT  阅读(3)  评论(0编辑  收藏  举报