並查集+路徑壓縮
parent[MAX_N] //父節點
rank[MAX_N] //樹的高度
初始化:
void init(int n) { for (int i=0;i<n;i++) { parent[i]=i; rank[i]=0; } }
查詢根節點:
int Find(int x) { if (parent[x]==x) return x; else
return parent[x]=Find(parent[x]); }
合並集合:
void Unite(int w,int v) { int x=Find(w); int y=Find(v);
if(x==y) return ;
if (rank[x]<rank[y])
parent[x]=y;
else{
parent[y]=x;
if (rank[x]==rank[y]) rank[x]++;
parent[x]=y; }
路徑壓縮:
①遞歸:
int Find(int x) //查找x元素所在的集合,回溯時壓縮路徑
{ if (x != parent[x]) { parent[x] = Find(parent[x]); //回溯時的壓縮路徑
} //從x結點搜索到祖先結點所經過的結點都指向該祖先結點
return parent[x]; }
②非遞歸:
int Find(int x) { int k, j, r; r = x; while(r != parent[r]) //查找跟節點
r = parent[r]; //找到跟節點,用r記錄下
k = x; while(k != r) //非遞歸路徑壓縮操作
{ j = parent[k]; //用j暫存parent[k]的父節點
parent[k] = r; //parent[x]指向跟節點
k = j; //k移到父節點
} return r; //返回根節點的值
}