323. 无向图中连通分量的数目


题目:

链接:https://leetcode-cn.com/problems/number-of-connected-components-in-an-undirected-graph/

给定编号从 0 到 n-1 的 n 个节点和一个无向边列表(每条边都是一对节点),请编写一个函数来计算无向图中连通分量的数目。

示例 1:

输入: n = 5 和 edges = [[0, 1], [1, 2], [3, 4]]

0 3
| |
1 --- 2 4

输出: 2
示例 2:

输入: n = 5 和 edges = [[0, 1], [1, 2], [2, 3], [3, 4]]

0 4
| |
1 --- 2 --- 3

输出:  1
注意:
你可以假设在 edges 中不会出现重复的边。而且由于所以的边都是无向边,[0, 1] 与 [1, 0]  相同,所以它们不会同时在 edges 中出现。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-connected-components-in-an-undirected-graph
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

解答:

DFS:维持一个未遍历过的节点,每次取一个为遍历过的节点,然后从它开始dfs,遍历所有可达的节点,也就是找到了一个连通分量。

class Solution {
public:
    int countComponents(int n, vector<vector<int>>& edges) {
        if(n<=0){
            return 0;
        }
        unordered_map<int,unordered_set<int> > edge_map;
        for(auto& edge:edges){
            edge_map[edge[0]].insert(edge[1]);
            edge_map[edge[1]].insert(edge[0]);
        }
        unordered_set<int> unvisited;
        for(int i=0;i<n;++i){unvisited.insert(i);}
        int res=0;
        while(unvisited.size()>0){
            // for(int x:unvisited){
            //     cout<<x<<" ";
            // }cout<<endl;
            auto cur=unvisited.begin();
            dfs(*cur,unvisited,edge_map);
            ++res;
        }
        return res;
    }

    void dfs(int cur,unordered_set<int>& unvisited,unordered_map<int,unordered_set<int> >& edge_map){
        unvisited.erase(cur);
        for(const int& neighbour:edge_map[cur]){
            if(unvisited.count(neighbour)){
                dfs(neighbour,unvisited,edge_map);
            }
        }
    }
};

 

 

 

并差集:(开始没想到,确实是个好方法)

class Solution {
public:
    vector<int> father;
    int Father(int i){
        if(father[i]!=i){
            return father[i]=Father(father[i]);
        }
        return i;
    }
    void merge(int x,int y){
        int px=Father(x),py=Father(y);
        father[px]=py;
    }
    int countComponents(int n, vector<vector<int>>& edges) {
        father.resize(n);
        for(int i=0;i<n;++i){
            father[i]=i;
        }
        for(auto& edge:edges){
            merge(edge[0],edge[1]);
        }
        unordered_set<int> tmp;
        for(int i=0;i<n;++i){
            if(tmp.count(Father(i))==0){//注意这里要调用Father(i)函数,因为可能i的父亲还没有更新为最靠上的祖先。
                tmp.insert(father[i]);//这里可以直接取father[i]的值,因为上面已经验证过了,当前father[i]的值一定是最靠上的祖先。
            }
        }
        return tmp.size();
    }   
};

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM