今天学了一下种类并查集和带权并查集,然后补了几道题。
题目:食物链
//带权并查集
#include<iostream>
using namespace std;
const int N = 50010;
int f[N], d[N];
int n, k;
int find(int x) {
if (f[x] != x) {
int t = find(f[x]);
d[x] += d[f[x]];
f[x] = t;
}
return f[x];
}
int main() {
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; i++) {
f[i] = i;
}
int res = 0;
while (k--) {
int t, x, y;
scanf("%d %d %d", &t, &x, &y);
if (x > n || y > n)res++;
else {
int fx = find(x), fy = find(y);
if (t == 1) {
if (fx == fy && (d[x] - d[y]) % 3)res++;
else if (fx != fy) {
f[fx] = fy;
d[fx] = d[y] - d[x];
}
}
else {
if (fx == fy && (d[x] - d[y] - 1) % 3)res++;
else if (fx != fy) {
f[fx] = fy;
d[fx] = d[y] + 1 - d[x];
}
}
}
}
printf("%d\n", res);
return 0;
}
种类并查集
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 2e5+7;
int f[N];
int n, m;
struct node {
int a, b, w;
}c[N];
int find(int x) {
if (f[x] == x)
return f[x];
else
return f[x] = find(f[x]);
}
bool compare(node a, node b) {
return a.w > b.w;
}
void merge(int x,int y) {
int fx = find(x), fy = find(y);
if (fx != fy) {
f[fy] = fx;
}
return;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= 2 * n; i++) {
f[i] = i;
}
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &c[i].a, &c[i].b, &c[i].w);
}
sort(c + 1, c + 1 + m, compare);
for (int i = 1; i <= m; i++) {
int a = c[i].a;
int b = c[i].b;
int w = c[i].w;
if (find(a)==find(b)) {
printf("%d\n", w);
return 0;
}
merge(a, b+n);
merge(b, a+n);
}
printf("0\n");
return 0;
}