【LeetCode】图的连通分量(并查集)

来源:互联网 发布:mac口红试色see sheer 编辑:程序博客网 时间:2024/05/29 06:54

这里写图片描述

求连通分量/城市个数:(如下图 找根结点,画正字)
这里写图片描述

C++ :

#include <iostream>#include <cstdio>#include <cstdlib>#include <memory.h>using namespace std;//查找图的联通分量class UnionFindSet {private:    int m_nN;    int* m_pParent;public:    UnionFindSet(int n);    ~UnionFindSet();    void Union(int i, int j);    int Find(int i);    void Print() const;    int CalcComponent(int N);};//m_pParent[i] = j ---- 第i个结点的父节点是jUnionFindSet::UnionFindSet(int n) {    m_nN = n;    m_pParent = new int[m_nN];    for(int i = 0; i < m_nN; i++){        m_pParent[i] = i;//默认自己是自己的父节点m_pParent    }}UnionFindSet::~UnionFindSet() {    if(m_pParent){        delete[] m_pParent;        m_pParent = NULL;    }}int UnionFindSet::Find(int i) {    if(i<0 || i>= m_nN)        return -1;    int root = i;    while (root != m_pParent[root]){//若当前根节点root(i)不是root的父节点        root = m_pParent[root];//则root = root的父节点(注意本循环内不要改变传入的i值!!!)    }    //循环结束后,root为i结点的根节点    //为了简化计算量,将Find()复杂度降为O(n)--> 压缩路径如下。    int tmp = i;    while (tmp != root){//第一次Find() 彻底遍历一遍:将遍历过的所有点的父节点直接指向根节点。这样 后序的查找会加速很多。        m_pParent[tmp] = root;//将当前遍历结点的父节点直接更改为根节点        tmp = m_pParent[tmp];//为了将父节点的父节点们一个个改为根节点,故用while循环。    }    return root;}void UnionFindSet::Union(int i, int j) {    if( i<0 || j<0|| i>= m_nN|| j>= m_nN)        return;    int root_i = Find(i);    int root_j = Find(j);    if(root_i != root_j){//若二者的父节点不一样,则将其一设为另一个结点的父节点(本次无特殊要求,则随意)        m_pParent[root_i] = root_j;    }}int UnionFindSet::CalcComponent(int N){    int *component = new int[N];//每个连通分量的结点数    memset(component, 0, N* sizeof(int));    for(int i = 0; i < N; i++){        int root_i = this->Find(i);//this: 调用者,即UnionFindSet的实例        component[root_i]++;    }    int nComponent = 0;//连通分量的总数(统计"首府"数目)    for(int i = 0; i < N; i++){        if(component[i] != 0){//计算每个岛屿的"首府"            nComponent++;        }    }    delete[] component;    return nComponent;}int main(){    const int N = 10;    UnionFindSet ufs(N);    ufs.Union(2,6);    ufs.Union(5,6);    ufs.Union(1,8);    ufs.Union(2,9);    ufs.Union(5,3);    ufs.Union(4,8);    ufs.Union(4,0);    int nComponent = ufs.CalcComponent(N);    cout << "ufs的联通分量为:" << nComponent << endl;}