带权并查集-CSDN博客

61 阅读2分钟
//悟空寻找龙珠 http://acm.hdu.edu.cn/showproblem.php?pid=3635

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int maxn = 10000 + 7;
int f[maxn], times[maxn], cnt[maxn];

int find(int x) {
	if (x == f[x]) return x;
	int t = f[x];
	f[x] = find(f[x]);
	times[x] += times[t];
	return f[x];

	/*    int r=x;
	while(r!=f[r]){
	r=f[r];//查 ,查完后root就是祖宗
	}
	int i=x,temp;
	while(i!=r){
	temp=f[i];
	times[i]+=times[temp];
	f[i]=r;
	i=temp;
	}//路径压缩
	return r;
	*/
}

void join(int x, int y) {
	int fx = find(x);
	int fy = find(y);
	if (fx != fy) {//若x,y的祖宗不一样 
		cnt[fy] += cnt[fx];
		//cnt[fx]=0;
		times[fx] = 1;
		f[fx] = fy;//为何不是f[x]=fy; //那肯定不是f[x]了,路径压缩后就没有以x为标记的集合了
	}
}

int main() {
	//freopen("data.in", "r", stdin);
	int T, kase = 0;
	scanf("%d", &T);
	while (T--) {
		printf("Case %d:\n", ++kase);
		int n, m;
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; i++) {//初始化 
			f[i] = i;//第i个龙珠的位置 
			cnt[i] = 1;//第i个城市的龙珠数目 
			times[i] = 0;//第i个龙珠移动次数,我觉得就是找了几次父类(路径压缩了的次数) 
		}
		while (m--) {
			char cmd[5];
			scanf("%s", cmd);
			int a, b;
			if (*cmd == 'T') {
				scanf("%d%d", &a, &b);
				join(a, b);
			}
			else if (*cmd == 'Q') {
				scanf("%d", &a);
				int temp = find(a);
				printf("%d %d %d\n", temp, cnt[temp], times[a]);
			}
		}
	}

	return 0;
}


//poj 1182

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 50000 + 7;
int f[maxn], w[maxn];
int cnt, n; 
int find(int x) {
	if (x != f[x])
	{
		int t = f[x]; f[x] = find(f[x]); w[x] = (w[x] + w[t]) % 3;
	}return f[x];
}
void join(int r, int x, int y) {
	int fx = find(x);
	int fy = find(y); 
	if (fx != fy) {
		f[fx] = fy; 
		w[fx] = (w[y] + r - w[x] + 3) % 3;
	}
}
int istrue(int d, int x, int y) {
	int fx, fy, r; if (x>n || y>n || (d == 2 && x == y)) 
		return 0; fx = find(x); fy = find(y); 
	if (fx != fy) return 1; 
	else { 
		if (w[x] == (d - 1 + w[y]) % 3)
			return 1;
		else return 0; 
	} 
}
int main() {
	int k; 
	cnt = 0; 
	scanf("%d%d", &n, &k);
	for (int i = 0; i <= n; i++) {
		f[i] = i; w[i] = 0;//权重
	}
	while (k--){ 
		int x, y, d; scanf("%d%d%d", &d, &x, &y); 
		if (!istrue(d, x, y)) 
			cnt++; 
		else join(d - 1, x, y); }printf("%d\n", cnt);
		return 0;
}

//poj 1962
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn = 20000 + 5, mod = 1000; 
int f[maxn], w[maxn]; 
int n;
int find(int x) { 
	if (x != f[x]) {
		int t = f[x]; 
		f[x] = find(f[x]); 
		w[x] = w[x] + w[t]; 
	}return f[x]; 
}void join(int x, int y) { 
	int fx = find(x); 
	int fy = find(y); 
	if (fx != fy) { 
		f[x] = y; 
		w[x] = abs(x - y) % mod;
	} 
}void intialization() {
	for (int i = 0; i <= n; i++){ 
		f[i] = i; w[i] = 0; 
	} 
}int main() {
	//freopen("data.in","r",stdin);
	int T; 
	scanf("%d", &T);
	while (T--) {
		scanf("%d", &n); 
		intialization(); 
		while (1) { 
			char cmd[5];
			int x, y; 
			scanf("%s", cmd);
			if (*cmd == 'E') { 
				scanf("%d", &x); 
				find(x); 
				printf("%d\n", w[x]); 
			} else if (*cmd == 'I') {
				scanf("%d%d", &x, &y); 
				join(x, y); }
			else if (*cmd == 'O')
				break; 
		} 
	}return 0;
}

\