并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。并查集通常包含两种操作,查找,合并。
模板代码:
朴素并查集+路径压缩优化:
1 2 3 4 5 6 7 8 9 10 11
| int find(int x) { if(p[x]!=x) p[x]= find(p[x]); return p[x]; }
for (int i = 1; i <= n; i ++ ) p[i] = i;
p[find(a)] = find(b);
|
并查集同时还可以维护同一类别节点数量。
1 2 3 4 5 6 7 8 9 10
| int size[N];
for (int i = 1; i <= n; i ++ ) { p[i] = i; size[i] = 1; }
size[find(b)] += size[find(a)]; p[find(a)] = find(b);
|
也可以同时维护到祖宗节点的距离。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int p[N], d[N];
int find(int x) { if (p[x] != x) { int u = find(p[x]); d[x] += d[p[x]]; p[x] = u; } return p[x]; } p[find(a)] = find(b); d[find(a)] = distance;
|
例题:https://www.acwing.com/problem/content/242/
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| #include<bits/stdc++.h> using namespace std; const int N =50005; int p[N]; int d[N]; int find(int x) { if(p[x]!=x) { int t = find(p[x]); d[x]+=d[p[x]]; p[x]=t; } return p[x]; } int main(void) { int n,k; cin>>n>>k; for(int i=1;i<=n;i++) p[i] = i; int t,x,y; int ans=0; while(k--) { cin>>t>>x>>y; if(x>n || y>n)++ans; else { int px= find(x); int py =find(y); if(t==1) { if(px==py && (d[x]-d[y])%3!=0) { ++ans; } else if(px!=py) { p[px] = py; d[px] = d[y]-d[x]; } } else { if(px==py && (d[x]-d[y]-1)%3!=0) ans++; else if(px!=py) { p[px] = py; d[px] = d[y]+1-d[x]; } } } } cout<<ans<<endl; }
|