题目:
链接: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(); } };