核心操作:
1、将两个集合合并
2、询问两个数是否在一个集合中
找父亲节点+路径压缩优化
核心代码:
int find(int x) //返回x的祖宗结点 + 路径优化 { if(p[x]!=x) p[x] = find(p[x]); // p[x]!=x,说明不是祖宗结点 return p[x]; }
return p[x]==x ? x : find(p[x]);
转载于:https://blog.csdn.net/wmy0217_/article/details/104972191
常见题型:
查询合并、连通块、道路连接、带权的连通图
HDU 1232题
题意:将所有独立的集合连接起来还需要几条路,那只要找到独立集合个数-1就可以
#include<bits/stdc++.h> using namespace std; #define IO ios_base::sync_with_stdio(false) #define forn(i,n) for(int i=0;i<n;i++) #define form(i,n) for(int i=1;i<=n;i++) #define N 100005 int p[N]; int find(int x) { if(p[x]!=x)p[x]=find(p[x]); return p[x]; } void combine(int a,int b) { int fa=find(a); int fb=find(b); if(fa!=fb)p[fa]=fb; } int main() { IO; int n,m; while(cin>>n){ if(n==0)break; cin>>m; int ans=0; form(i,n)p[i]=i; forn(i,m){ int a,b; cin>>a>>b; combine(a,b); } form(i,n)if(p[i]==i)ans++; cout<<ans-1<<endl; } return 0; }