547. Number of Provinces

547. Number of Provinces

Link: https://leetcode-cn.com/problems/number-of-provinces/

There is  n a city, some of which are connected to each other, and others are not connected. If the city  a is b directly connected to the city  , and the city  b is  c directly connected to the city, then the city  a is c indirectly connected to the city  .

A province  is a group of directly or indirectly connected cities. The group does not contain other unconnected cities.

Give you a  n x n matrix  isConnected , which  isConnected[i][j] = 1 means that the  i first city and the  j first city are directly connected, but  isConnected[i][j] = 0 that the two are not directly connected.

Returns  the number of provinces in the matrix  .

Example 1:

Input: isConnected = [[1,1,0],[1,1,0],[0,0,1]]
 Output: 2

Example 2:

Input: isConnected = [[1,0,0],[0,1,0],[0,0,1]]
 Output: 3

 

prompt:

  • 1 <= n <= 200
  • n == isConnected.length
  • n == isConnected[i].length
  • isConnected[i][j] For  1 or 0
  • isConnected[i][i] == 1
  • isConnected[i][j] == isConnected[j][i]

Idea: It is an obvious problem of union search. It starts with n independent sets, and each time they are merged, the number of sets decreases by 1. We use path compression for optimization (adding rank-based merging is also possible, but if the time is not particularly deadly, the optimization of rank-based merging is limited, which will increase the code complexity).

class Solution {
public:

    int Father[210];

    int Find(int x){
        if( x != Father[x] ){
            return Father[x] = Find(Father[x]);
        }
        return Father[x];
    }

    void Union(int A,int B,int &Single){
        int FA = Find(A), FB = Find(B);
        if( FA != FB ){
            Father[FA] = FB;
            -- Single;//每成功合并一次 集合数就少一
        }
    }

    int findCircleNum(vector<vector<int>>& isConnected) {
        int n = isConnected.size(), i, j, Single = n;
        for(i = 0; i < n; ++ i){
            Father[i] = i;
        }
        for(i = 0; i < n; ++ i){
            for(j = 0; j < n; ++ j){
                if( isConnected[i][j] ){
                    Union(i, j, Single);
                }
            }
        }  
        return Single;
    }
};

Increase the combined version by rank:

class Solution {
public:

    int Father[210];
    int Rank[210];

    int Find(int x){
        if( x != Father[x] ){
            return Father[x] = Find(Father[x]);
        }
        return Father[x];
    }

    void Union(int A,int B,int &Single){
        int FA = Find(A), FB = Find(B);
        if( FA != FB ){
            if(Rank[FA] < Rank[FB]){
                Father[FA] = FB;
            }else if(Rank[FA] == Rank[FB]){
                Father[FA] = FB;
                ++ Rank[FB];
            }else{
                Father[FB] = FA;
            }
            -- Single;//每成功合并一次 集合数就少一
        }
    }

    int findCircleNum(vector<vector<int>>& isConnected) {
        int n = isConnected.size(), i, j, Single = n;
        memset(Rank,0,sizeof(Rank));
        for(i = 0; i < n; ++ i){
            Father[i] = i;
        }
        for(i = 0; i < n; ++ i){
            for(j = 0; j < n; ++ j){
                if( isConnected[i][j] ){
                    Union(i, j, Single);
                }
            }
        }  
        return Single;
    }
};

This way of writing is to ensure that Rank correctly reflects the height of the tree, but at the same time, overly complex if-else statements will reduce the execution performance of the program. If we do not need to ensure the correctness of Rank, we can:

class Solution {
public:

    int Father[210];
    int Rank[210];

    int Find(int x){
        if( x != Father[x] ){
            return Father[x] = Find(Father[x]);
        }
        return Father[x];
    }

    void Union(int A,int B,int &Single){
        int FA = Find(A), FB = Find(B);
        if( FA != FB ){
            if(Rank[FA] < Rank[FB]){
                Father[FA] = FB;
                ++ Rank[FB];
            }else{
                Father[FB] = FA;
                ++ Rank[FA];
            }
            -- Single;//每成功合并一次 集合数就少一
        }
    }

    int findCircleNum(vector<vector<int>>& isConnected) {
        int n = isConnected.size(), i, j, Single = n;
        memset(Rank,0,sizeof(Rank));
        for(i = 0; i < n; ++ i){
            Father[i] = i;
        }
        for(i = 0; i < n; ++ i){
            for(j = 0; j < n; ++ j){
                if( isConnected[i][j] ){
                    Union(i, j, Single);
                }
            }
        }  
        return Single;
    }
};

 

 

 

Guess you like

Origin blog.csdn.net/qq_39304630/article/details/112317465