fork download
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. typedef long long ll;
  6. typedef pair<int, int> ii;
  7.  
  8. const int INF = 1e9;
  9. const ll LINF = 1e18;
  10.  
  11. const int N = 1e5 + 5;
  12.  
  13. int n, m;
  14. int p[N]; // p[u]: cha của u
  15. int sz[N]; // sz[u]: Số đỉnh có trong tập hợp (cây / thành phần liên thông) do u đại diện
  16.  
  17. void initSet() {
  18. for (int u = 1; u <= n; u++) {
  19. p[u] = u;
  20. sz[u] = 1;
  21. }
  22. }
  23.  
  24. // Tìm đại diện của tập hợp (cây / thành phần liên thông) chứa u
  25. int findSet(int u) {
  26. if (p[u] == u) return u;
  27. return p[u] = findSet(p[u]);
  28. }
  29.  
  30. // Gộp tập hợp chứa u với tập hợp chứa v
  31. // Trả về true nếu gộp thành công, false nếu u và v đã chung một tập hợp
  32. bool unionSet(int u, int v) {
  33. u = findSet(u);
  34. v = findSet(v);
  35. if (u == v) return false;
  36. if (sz[u] < sz[v]) swap(u, v);
  37. p[v] = u;
  38. sz[u] += sz[v];
  39. return true;
  40. }
  41.  
  42. vector<int> comp[N]; // comp[u]: danh sách các đỉnh có thành phần liên thông do u đại diện
  43.  
  44. int main() {
  45. ios::sync_with_stdio(false);
  46. cin.tie(nullptr);
  47. cin >> n >> m;
  48.  
  49. initSet();
  50.  
  51. int num_cc = n; // Số thành phần liên thông
  52. for (int i = 0; i < m; i++) {
  53. int u, v;
  54. cin >> u >> v;
  55. num_cc -= unionSet(u, v);
  56. }
  57.  
  58. for (int u = 1; u <= n; u++) {
  59. comp[findSet(u)].push_back(u);
  60. }
  61.  
  62. cout << num_cc << '\n';
  63.  
  64. for (int u = 1; u <= n; u++) {
  65. if (findSet(u) == u) {
  66. cout << comp[u].size() << ' ';
  67. for (int v : comp[u]) cout << v << ' ';
  68. cout << '\n';
  69. }
  70. }
  71. }
Success #stdin #stdout 0.01s 5764KB
stdin
12 10
1 4
2 3
3 6
4 5
6 7
8 9
8 10
9 11
11 8
11 12 
stdout
3
3 1 4 5 
4 2 3 6 7 
5 8 9 10 11 12