1. 程式人生 > 其它 >C++並查集

C++並查集

#include<stdc++.h>
#include <iostream>
using namespace std;


class ufset{
public:
  static const int N = 100010;
  int p[N]; // p[i]看做i的指標,該指標指向其父節點。
  int cnt[N]; // cnt[i]看做i為root時候的樹節點總個數。

  ufset(int size){
    for(int i = 0; i < size; i++){
      p[i] = i; // 每個i都是root
      cnt[i] = 1; // 每個i都是root,節點數為1
    }
  }

  int find(int i){ //查詢roor
    if(p[i] != i){   // 如果當前節點不是root,
      p[i] = find(p[i]);//找到其父節點的root,當前節點指向其父節點的root
    }
    return p[i]; // 當前節點的父節點一定為集合的root
  }

  bool isUnion(int le, int ri){ // 兩個節點時候一個集合
    return p[le] == p[ri]; //兩節點的root是否相同
  }

  void unionD(int le, int ri){ // 合併兩個集合
    cnt[find(le)] += cnt[find(ri)]; //兩集合節點數相加
    p[find(ri)] = find(le);//右集合指向左集合的root
  }

  int cntI(int i){ // 計算當前集合數量
    return cnt[find(i)];// 找到root,再找cnt[root]
  }

};

int main(){
  ufset us(10);
  us.unionD(1,2);
  us.unionD(3,2);

  us.unionD(4,5);
  us.unionD(6,5);
  

  us.unionD(7,9);
  cout << "find(): "; 
  for(int i = 1; i < 10; i++){
    cout << us.find(i) << ",";
  }

  cout << endl << "p[]: ";
  for(int i = 1;i < 10; i++){
    cout << us.p[i] << ",";
  }
    cout << endl << "cnt[]: ";
  for(int i = 1;i < 10; i++){
    cout << us.cnt[i] << ",";
  }
  
  us.unionD(1,9); // 兩個集合合併
  cout << "兩個集合合併:us.unionD(1,9);" << endl;
  cout << endl << "p[]: ";
  for(int i = 1;i < 10; i++){
    cout << us.p[i] << ",";
  }
  
  cout << endl << "cnt[]: ";
  for(int i = 1;i < 10; i++){
    cout << us.cnt[i] << ",";
  }
  cout << endl << us.cntI(9);
  cout << endl << "p[]: ";
  for(int i = 1;i < 10; i++){
    cout << us.p[i] << ",";
  }
  return 0;
}