给定一个节点数组和一个边数组,如何计算连接图的数量?
为了详细说明quasiverse的答案,这里是一个简短的伪代码:
make_set(v) 创建一个只有v作为成员的新集合。
union(x, y) 合并两个集合x和y。新集合的代表元素从两个集合中选择一个。
get_representatve(v) 返回给定节点所属集合的代表元素。
在图G =(V,E)中查找连通分量:
foreach vertex v in V:
make_set(v)
foreach edge (u, v) in E:
if get_representatve(u) != get_representatve:
union(u, v)
是的,有一种算法,其时间复杂度与图的大小成线性关系,为O(|V| + |E|)。
visited := the empty set
count := 0
for each vertex v in vertices:
if v not in visited:
count++
add v and all nodes reachable from v to visited
return count
对于无向图,可以使用简单的DFS算法在O(n)时间内完成。具体步骤如下:
定义一个名为explore
的过程,该过程查找从给定节点可以到达的所有节点。这只是一个递归的DFS过程,在每个节点处,您需要找到该节点的所有子节点并将它们推入堆栈中。
要找到答案,请从任何节点开始DFS,并在该节点上启动explore
过程。保持一个整数(假设为cc
),并在每次调用explore
过程时将其传递给它。此外,保持一个哈希映射/字典或类似物,将cc
映射到相应的节点。在explore
过程的每个级别上,将当前节点映射到此时的cc
。每次递归调用explore
过程时,都将相同的cc
值传递给它。
explore
返回到DFS循环时,增加cc
并将该值传递给下一次。完成整个DFS后,您将拥有一个将每个节点映射到其相应连接组件编号的字典。此过程结束时cc
的值可以告诉您图中有多少个连接组件。function explore(node, graph, cc, map){
map(currentNode) = cc
//find all children of current node, and push onto stack.
//mark current node as visited
for i in stack:
explore(i, graph, cc, map)
}
function DFS{
int cc = -1
for node in keysOfGraph:
if not visited:
cc++
explore(node, graph, cc, map)
return cc
}
来自Dasgupta算法(第3.2.3节)