並查集(union-find)模板
阿新 • • 發佈:2019-01-07
#include<cstdio> #include<cstring> #include<vector> using namespace std; const int mx = 100005; int fa[mx], rk[mx]; vector<int> element[mx]; inline void init(int n) { memset(fa, -1, sizeof(fa)); ///為防止資料中有0號節點,可先將所有的父節點置為-1 memset(rk, 0, sizeof(rk)); } int find(int x) {return ~fa[x] ? fa[x] = find(fa[x]) : x;} void merge(int x, int y) { x = find(x), y = find(y); if (x == y) return; ///已合併 if (rk[x] < rk[y]) fa[x] = y; else { fa[y] = x; if (rk[x] == rk[y]) ++rk[x]; } } inline bool same(int x, int y) {return find(x) == find(y);} ///輸出有多少個不同集合 int set_counter(int n) { int sum = 0; for (int i = 0; i < n; ++i) if (find(i) == -1) ++sum; return sum; } ///輸出所有集合 void outputset(int n) { int i, j; for (i = 0; i < n; ++i) element[i].clear(); for (i = 0; i < n; ++i) element[~find(i) ? find(i) : i].push_back(i); for (i = 0; i < n; ++i) if (element[i].size()) { putchar('{'); for (j = 0; j < element[i].size() - 1; ++j) printf("%d,", element[i][j]); /// 注意陣列內元素本身就是有序的 printf("%d}\n", element[i][element[i].size() - 1]); } } int main() { int n, m, a, b; ///m是(a,b)的對數 while (~scanf("%d%d", &n, &m)) { init(n); while (m--) { scanf("%d%d", &a, &b); merge(a, b); } printf("%d\n", set_counter(n)); ///輸出有多少個不同集合 outputset(n);///輸出所有集合 } return 0; }