食物链 带权/种类并查集

复习一下带权并查集,感到大脑空空,题目链接:食物链

整理了一下笔记:

食物链 带权/种类并查集_第1张图片

 

#include 
using namespace std;
const int N = 5e5+10;
int p[N], 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];
}
int main() {
	int n, k, op, x, y, ans = 0; scanf("%d%d", &n, &k);
	for(int i = 1; i<=n; i++) p[i] = i;
	while(k--){
		scanf("%d%d%d", &op, &x, &y);
		if(x > n||y > n){
			ans++;
			continue;
		}
		int px = find(x), py = find(y);
		if(op == 1){
			if(px==py){
				if((d[x]-d[y])%3) ++ans;
			}
			else{
				p[px] = py;
				d[px] = d[y]-d[x];
			}
		}
		else{
			if(px==py){
				if((d[x] - d[y] - 1)%3) ++ans;
			}
			else{
				p[px] = py;
				d[px] = d[y] - d[x] +1;
			}
		}
	}
	cout<

然后学习了一下种类并查集

食物链 带权/种类并查集_第2张图片

#include 
using namespace std;
const int N = 5e5+5;
int p[N*3];
int find(int x){
	if(p[x]!=x) return p[x] = find(p[x]);
	return p[x];
}
void Union(int x, int y){
	int px = find(x), py = find(y);
	if(px==py) return;
	p[px] = py;
}
int main() {
	int n, k, op, x, y, ans = 0; scanf("%d%d", &n, &k);
	for(int i = 1; i<=3*n; i++) p[i] = i;
	while(k--){
		scanf("%d%d%d", &op, &x, &y);
		if(x>n || y>n){
			 ++ans;
			 continue;
		}
		int px = find(x), py = find(y);
		if(op == 1){
			if(px == find(y+n) || py == find(x+n)) ++ans;
			else{
				Union(x, y);
				Union(x + n, y + n);
				Union(x + 2*n, y + 2*n);
			}
		}
		else{
			if(px==py || px == find(y+n)){
				++ans;
			}
			else{
				Union(x + n, y);
				Union(x + 2*n, y + n);
				Union(x, y + 2*n);
			}
		}
	}
	cout<

 

你可能感兴趣的:(算法)