数据结构:带权—种类并查集模板
带权并查集
点击查看折叠代码块
/*
给出一个区间的长度 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;
}