数据结构:带权—种类并查集模板

带权并查集

点击查看折叠代码块
/*
给出一个区间的长度 N,及 M 个子区间和, 形如:x y z, 表示
子区间 [x, y] 的和为 z
如果一个“子区间和”与前面的“子区间和”冲突,即为错误(而且这个“子区间和”将在接下来的判断中被忽略)。
求总错误个数。
带权并查集
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=2e5+10;
int fa[maxn];
int sum[maxn];
int getfa(int x){
	if(x==fa[x]) return x;
	else{
		int root=getfa(fa[x]);
		sum[x]+=sum[fa[x]];
		return fa[x]=root;
	}
}
int n,m;

int main(){
	while(~scanf("%d%d",&n,&m)){
		for (int i=0;i<=n;i++){
			fa[i]=i;sum[i]=0;
		}
		int ans=0;
		for (int i=1;i<=m;i++){
			int x,y,s;
			scanf("%d%d%d",&x,&y,&s);
			x--;
			int f1=getfa(x),f2=getfa(y);
			if(f1==f2){
				if(sum[y]-sum[x]!=s) ans++;
			}
			else{
				fa[f2]=f1;
				sum[f2]=sum[x]+s-sum[y];
			}
		}
		printf("%d\n",ans);	
	}
	
	return 0;
}

种类并查集

点击查看折叠代码块
/*
种类并查集
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=50000+10;
int fa[maxn],r[maxn];//0同类,1表示x吃其祖先,2表示x被祖先吃 
int getfa(int x){
	if(x==fa[x]) return x;
	else{
		int root=getfa(fa[x]);
		r[x]=(r[x]+r[fa[x]]) % 3;
		return fa[x]=root;
	}
}
int n,k;

int main(){
	scanf("%d%d",&n,&k);
	for (int i=1;i<=n;i++){
		fa[i]=i;
		r[i]=0;
	}
	int d,x,y,ans=0;
	for (int i=1;i<=k;i++){
		scanf("%d%d%d",&d,&x,&y);
		if(x>n || y>n) ans++;
		else{
			if(d==2 && x==y) ans++;
			else{
				int f1=getfa(x),f2=getfa(y);
				if(f1==f2){//祖先相同 
					if((r[x]-r[y]+3) % 3!=d-1) ans++;
				}
				else {
					fa[f1]=f2;
					r[f1]=(-r[x]+d-1+r[y]+3) % 3;
				}
			}
		}
	}
	printf("%d\n",ans);
	return 0; 
}
posted @ 2020-07-28 19:49  wsl_lld  阅读(132)  评论(0编辑  收藏  举报