并查集基础:
查找、路径压缩、合并
```c++
int fa[maxn];
int find(int x){
if(fa[x] == x) return x;
else return fa[x] = find(fa[x]);
}
void union(int x, int y){
fa[find(x)] = find(y);
}
```
经典带权并查集:HDU3038
题目大意:
```文本框
现给出n个数字组成的序列,编号为1~n;
给出m个查询,每个查询的答案由a,b,s三个数组成,表示从第a个数加到第b个数的和为s;
但是其中有一些是有矛盾的(或者说错误的),求错误的查询答案有多少个。
```
AC代码:
```c++
#include<bits/stdc++.h>
#define ll long long
#define db double
#define PII pair<int, int>
using namespace std;
const ll maxn = 2e5 + 10;
int fa[maxn], sum[maxn];
int find(int i){
if(fa[i] == i) return i;
int tmp = fa[i];
fa[i] = find(fa[i]);
sum[i] += sum[tmp]; // 路径压缩,并且需要所有上面节点的值,与普通并查集不一样的点
return fa[i];
}
int main(){
int n, m;
while(scanf("%d%d", &n, &m) != EOF){
int ans = 0;
for(int i = 0; i <= n; i++){
fa[i] = i;
sum[i] = 0;
}
for(int i = 0; i < m; i++){
int a, b, s;
scanf("%d%d%d", &a, &b, &s);
a--;
int aa = find(a);
int bb = find(b);
if(aa != bb){
fa[bb] = aa;
sum[bb] = sum[a] + s - sum[b];
}
else{
if(sum[b] - sum[a] != s) ans++;
}
}
printf("%d\n", ans);
}
return 0;
}
```