并查集是常见而且好用的一种数据结构。原因在于代码简练而且方便维护各种额外信息。带权并查集就是并查集的一种应用方式。原理其实就是普通并查集额外维护了一个结点的权数组。
例题:

本题的关系有三层 -> a -> b -> c -> ,但不同的是本题的关系是有向的,也就是说a和b如果是敌对关系,那么b和a就不是敌对关系。
关系传递的本质实际上是向量的运算。
还是设 d[x] 表示 x 与 fa[x] 的关系,0 代表是同类,1 代表是x吃fa[x], 根据关系图自然2就代表x被fa[x]吃。
#include<iostream>
using namespace std;
const int N = 500010;
int p[N];
int d[N];//带权并查集的权值0 1 2 三个值分别表示是同类,吃根节点,和被根节点吃;
int n,m,k,a,b;
int find(int x)
{
if(p[x] == x) return x;
int r = find(p[x]);
d[x] += d[p[x]];
return p[x] = r;
}
int main(){
cin>>n>>m;
for(int i = 0 ; i <= n ; i++){
p[i] = i;
}
int res = 0;
for(int i = 0 ; i < m ; i ++){
cin>>k>>a>>b;
if(a>n || b>n){
res++;continue;
}
else if(k == 2 && a == b){
res++;continue;
}else{
int x = find(a);int y = find(b);
int t = 0;
if(k==2) t = 1;
if(x == y){
if( (((d[a] - d[b]) % 3) + 3) % 3 != t ){
res ++;
}
}else{
p[x] = y;
d[x] = d[b] - (d[a] - t);
}
}
}
cout<<res<<endl;
return 0;
}
来源:https://www.cnblogs.com/Flydoggie/p/12283513.html