给定编号从 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
1.dfs
参考:https://blog.csdn.net/qq_19782019/article/details/82590527
2.迭代+栈
初始时,起始顶点V0入栈,其对应的visited[V0]设置为True,迭代过程如下:
3.bfs
参考:https://blog.csdn.net/qq_19782019/article/details/82659964
4.并查集
1.dfs
class Solution:
def dfs(self,i,graph,visited):
for t in graph[i]:
if t not in visited:
visited.add(t)
self.dfs(t,graph,visited)
def countComponents(self, n: int, edges: List[List[int]]) -> int:
from collections import defaultdict
graph = defaultdict(list)
for x,y in edges:
graph[x].append(y)
graph[y].append(x)
visited = set()
res = 0
for i in range(n):
if i not in visited:
visited.add(i)
res += 1
self.dfs(i,graph,visited)
return res
2.栈
class Solution:
def stack(self,i,graph,visited):
stack = []
stack.append(i)
while stack:
i = stack.pop(-1)
for t in graph[i]:
if t not in visited:
visited.add(t)
stack.append(t)
def countComponents(self, n: int, edges: List[List[int]]) -> int:
from collections import defaultdict
graph = defaultdict(list)
for x,y in edges:
graph[x].append(y)
graph[y].append(x)
visited = set()
res = 0
for i in range(n):
if i not in visited:
visited.add(i)
res += 1
self.stack(i,graph,visited)
return res
3.bfs
class Solution:
def bfs(self,i,graph,visited):
Q = []
Q.append(i)
while Q:
i = Q.pop(0)
for t in graph[i]:
if t not in visited:
visited.add(t)
Q.append(t)
def countComponents(self, n: int, edges: List[List[int]]) -> int:
from collections import defaultdict
graph = defaultdict(list)
for x,y in edges:
graph[x].append(y)
graph[y].append(x)
visited = set()
res = 0
for i in range(n):
if i not in visited:
visited.add(i)
res += 1
self.bfs(i,graph,visited)
return res
4.并查集
class Solution:
def countComponents(self, n: int, edges: List[List[int]]) -> int:
def find(x,parent):
while parent[x] != -1:
x = parent[x]
return x
def union_vertices(x,y,parent,rank):
a=find(x,parent)
b=find(y,parent)
if a!=b:
if rank[a]>rank[b]:
parent[b] = a
elif rank[a]
附上并查集basic code
parent = [-1] * 100000
# 用rank来记录高度
rank = [0] * 100000
# 每个集合中的元素个数
count = [1] * 100000
def find(x,parent):
while parent[x] != -1:
x = parent[x]
return x
def union_vertices(x,y,parent,rank,count):
a=find(x,parent)
b=find(y,parent)
if a!=b:
if rank[a]>rank[b]:
parent[b] = a
count[a]+=count[b]
elif rank[a]
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。
其实判断一个图是否存在环已经有相应的算法,此文用并查集来判断一个图是否有环。
我们可以用一个一维数组parent[] 来记录子集合。
看下面这个图:
0
| \
| \
1——2
对每一条边的两个顶点加入集合,发现两个相同的顶点在一个子集合中,就说明存在环。
初始化:parent[n] 的每个元素都为-1,共有n个子集合,表示集合只有当前顶点一个元素
0 1 2
-1 -1 -1
然后逐个处理每条边。
边0-1:我们找到两个子集合 0 和1,因为他们在不同的子集合,现在需要合并他们(Union). 把其中一个子集合作为对方的父集合.
0 1 2 <----- 1 成为 0 的 父集合 (1 现在代表集合 {0, 1})
1 -1 -1
边1-2:1属于属于子集合1,2属于子集合2,因此合并他们。
0 1 2 <----- 2 作为 1的父集合 (2 现在代表集合 {0, 1, 2})
1 2 -1
边0-2: 0是在子集合2,2也是在子集合2, 因为 0->1->2 // 1 是0 父集合 并且 2 是1的父集合 。因此,找到了环
在判断两个点之间是否有环时,判断它们的父亲节点是否是一个,如果是,则有环
a=find(x,parent)
b=find(y,parent)
if a == b:就找到了环
参考:https://www.cnblogs.com/acm-jing/p/4655513.html