并查集 求连通图问题

解题思路

并查集 ,重点在理解每个节点都要记录它的父亲节点
为节省查找时间,需要对路径进行压缩
如果当前节点能都与其他树合并 ,则应该讲集合总数减1

代码

class Solution {
public:
//利用并查集,字典: std::unordered_map  , 倒树
//find merge add to tree 
    class CUnionFind
    {
    private:
      std::unordered_map<int,int> tset;
      int nConnectedCount=0;
    public:
       bool add(int x)
       {
           if(tset.count(x)==0) 
           {
               tset[x] = -1;
               nConnectedCount++;
               return true;
           }else
           {
               return false;
           }
       }
/// return root
       int find(int x)
       {
           while(tset[x]!=-1 )
           {
               x= tset[x];
           }
         

           return x;
       }

       bool merge(int x,int y )
       {
            //4->9->2->-1   vs 7->-1   
            auto rootOfX = find(x);
            auto rootOfY = find(y);
            if(rootOfX == rootOfY)  return false;
            
            tset[rootOfX] = rootOfY;
            nConnectedCount --;   //如果非同根节点 才进行合并

           
             
             //here need zip
              //从下往上进行 
            //   x -> parent   x+1 -->parent
            while(x != rootOfY)
            {
                int nextNode= tset[x];
                tset[x]= rootOfY;
                x= nextNode;
            }

            while(y != rootOfY )
            {
                int nextNode = tset[y];
                tset[y] = rootOfY;
                y= nextNode;
            }

            return true;
       }

       int getConnectedCount() {
           return nConnectedCount;
       }
         void printTree()
         {
             for(auto x: tset)
             {
                 std::cout << x.first <<":" << x.second <<", " ;
             }
             std::cout << std::endl;
         }
    };
    
    int findCircleNum(vector<vector<int>>& isConnected) {

        //e.g [[1,1,1],[1,1,1],[1,1,1]]
        //output:
        // 0:-1, 
        // 1:0, 0:-1, 
        // 2:0, 1:0, 0:-1, 
    //遍历每一行,tU.add 
    //如果发现有结合点 就合并
        CUnionFind tU;
        for(int i=0;i<isConnected.size();i++)
        {
            tU.add(i);
          //  std::cout << i << std::endl;
            for(int j=0;j<i;j++)
            {
                if(isConnected[i][j])  tU.merge(i,j);
            }

          //  tU.printTree();
        }


          return tU.getConnectedCount();
        


    }
};

题目描述

  1. 省份数量
    有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。

posted @ 2021-05-21 14:34  boyang987  阅读(78)  评论(0编辑  收藏  举报