并查集
#include<iostream>
#define VERTICES 6
using namespace std;
void initialise(int parent[],int rank[]){//初始化数组,rank树高
int i;
for(i=0;i<VERTICES;i++){
parent[i]=-1;
rank[i]=0;
}
}
int find_root(int x,int parent[]){
int x_root = x;
while(parent[x_root]!=-1){
x_root = parent[x_root];
}
return x_root;
}
// 1 union successfully, 0 -failed
int union_vertices(int x, int y, int parent[],int rank[]){
int x_root = find_root(x,parent);//0 1 1/2
int y_root = find_root(y,parent);//1 2 3
if(x_root == y_root){//如果两树的根相同
return 0;
}else{
//parent[x_root]=y_root;
/*
以上按照数组中的边数和顶点数连接
以下路径压缩
*/
if(rank[x_root] > rank[y_root]){
parent[y_root] = x_root;
}else if(rank[y_root] > rank[x_root]){
parent[x_root] = y_root;
}else{
parent[x_root] = y_root;
rank[y_root]++;//当两树的根相同时,树高加1
}
return 1;
}
}//检测是否有环
int main(){
int parent[VERTICES]={0};
int rank[VERTICES] = {0};//路径压缩功能数
int edges[6][2]{
{0,1},{1,2},{1,3},
{3,4},{2,5},{5,4}
};
initialise(parent,rank);//将数组初始化为-1
for(int i=0;i<6;i++){
int x = edges[i][0];
int y = edges[i][1];
if(union_vertices(x,y,parent,rank)==0){
cout<<"Cycle detected!"<<endl;
exit(0);
}
}
cout<<"not Cycle found"<<endl;
system("0");
return 0;
}
以上是并查集建立树和路径压缩的代码
实际应用:
其实就是将数组中的有关系的元素连成一棵树,对应数组中有几个负数就是有几棵树,即该学校有几个社团。
实例: {1,2,3}为一棵树
{4,5}为一棵树
_set[]:{-,1,1,-,4}("-"表示负数)
#include<iostream>
#pragma once
using namespace std;
class UnionSet {
public:
UnionSet(int n = 6) {//初始化parent[]
for (int i = 0; i < 6; i++) {
_set[i] = -1;
}
_n = n;
}
int GetRoot(int p) {//得到树根的下标
while (_set[p] >= 0) {//寻根
p = _set[p];
}
return p;
}
void UnionFriends(int p1, int p2) {//parent[][]
int root1 = GetRoot(p1);
int root2 = GetRoot(p2);
if (root1 != root2) {
_set[root1] = _set[root1] + _set[root2];
_set[root2] = root1;//建立树,将不同根的节点树连接
}
}
int friends(int n, int m, int r[][2]) {//并查集主功能函数
int count = 0;
for (int i = 0; i < m; i++) {
UnionFriends(r[i][0], r[i][1]);
}
for (int i = 1; i < n + 1; i++)
{
if (_set[i] < 0) {
count++;
}
}
return count;
}
private:
int _set[6];
int _n;
};
int main() {
int n = 5, m = 3;//n人数,m好友关系
int r[3][2] = {
{1,2},{2,3},{4,5}//有三个关系,其中两个关系重叠,总共有两个社团
};
UnionSet us;
int ret = us.friends(n, m, r);
cout << "社团的人数为:" << ret << endl;
system("pause");
return 0;
}