並查集模板及對應模板題
阿新 • • 發佈:2019-02-13
並查集是一種樹型的資料結構,用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。常常在使用中以森林來表示。
集就是讓每個元素構成一個單元素的集合,也就是按一定順序將屬於同一組的元素所在的集合合併。
(來自百度百科)
並查集的操作主要有3個:
1,初始化:把每個點所在集合初始化為其自身。通常來說,這個步驟在每次使用該資料結構時只需要執行一次,無論何種實現方式,時間複雜度均為O(N)。
2,查詢:查詢元素所在的集合,即根節點。
3,合併:將兩個元素所在的集合合併為一個集合。
貼模板程式碼
int cnt,pre[maxn],n; void init(){ cnt=n; //n為節點數 for(int i=0;i<n;i++) pre[i]=i; } int find(int p){ int root=p; while(pre[root]!=root) root=pre[root]; int temp; while(pre[p]!=p){ // 儘可能簡便地縮短樹的高度 temp=pre[p]; pre[p]=root; p=temp; } return root; } void connect(int x,int y){ int fx=find(x),fy=find(y); if(fx!=fy){ pre[fx]=fy; cnt--; } }
典型模板題:hdu 1232(求聯通分支數)
AC程式碼
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #define INF 0x3f3f3f3f using namespace std; int n,m,pre[1005]; int find(int k){ int root=k; while(pre[root]!=root) root=pre[root]; int temp; while(pre[k]!=k){ temp=pre[k]; pre[k]=root; k=temp; } return root; } void connect(int x, int y){ int fx=find(x), fy=find(y); if(fx!=fy){ pre[fx]=fy; n--; } } void init(){ for(int i=1;i<=n;i++){ pre[i]=i; } } int main() { freopen("input.txt","r",stdin); int a,b; while(scanf("%d%d",&n,&m) && n){ init(); for(int i=0;i<m;i++){ scanf("%d%d",&a,&b); connect(a,b); } printf("%d\n",n-1); } return 0; }