並查集(按秩合併、路徑壓縮)
阿新 • • 發佈:2019-01-02
演算法分類:
資料結構
演算法原理:
通過find函式找出該節點的根節點,
通過UNION函式將兩棵樹合併。
加入rank[N]來記錄每個節點的秩(即樹的高度),並按秩進行合併,可避免合併時的最糟糕情況,(樹形為一條直線)
通過路徑壓縮可以減少每次尋找根節點的次數。
演算法時間複雜度:
最壞情況為O(mlogn)
一般為O(m)
程式碼實現:(HDU1232-暢通工程)
/* * HDU 1232 暢通工程 * 並查集 */ #include <iostream> using namespace std; const int SIZE = 1005; int root[SIZE]; int rank[SIZE]; int find(int x) { int y = x; while (root[y] != y) { y = root[y]; } int temp, head = y; y = x; while (root[y] != y) { temp = root[y]; root[y] = head; y = temp; } return head; }; void UNION(int x, int y) { int f1 = find(x); int f2 = find(y); if (rank[f1] <= rank[f2]) { root[f1] = f2; if (rank[f1] == rank[f2]) { rank[f2] ++; } } else { root[f2] = f1; } }; int main() { int N, M, s, e, count; while (scanf("%d%d",&N,&M)!=EOF, N) { for (int i = 1; i <= N; ++ i) root[i] = i; for (int i = 0; i < M; ++ i) { scanf("%d%d",&s,&e); UNION(s,e); } count = -1; for (int i = 1; i <= N; ++ i) { if (root[i] == i) ++ count; } printf("%d\n",count); } }