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;
}

posted @ 2022-03-27 10:01  子于舟  阅读(128)  评论(0)    收藏  举报