我对图论并不是很熟悉,但我会尝试解释我的问题。 我有这样一个词典:
{67: [68, 332],
68: [67],
265: [266],
266: [265],
332: [67, 333],
333: [332, 334],
334: [333, 335],
335: [334, 336],
336: [335]}
此dict的键是节点,值是图的边缘。 我们如何在此图中找到连接的组? [有两组 - 265-> 266和67-> ...-> 366]
答案 0 :(得分:2)
我相信你在谈论Tarjan's strongly connected components algorithm。
这是我认为正确的Python实现。您必须将字典转换为边缘列表,如[('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'E'), ('E', 'A'), ('A', 'E'), ('C', 'A'), ('C', 'E'), ('D', 'F'), ('F', 'B'), ('E', 'F')]
:
import itertools
def strong_connect(vertex):
global edges, indices, lowlinks, connected_components, index, stack
indices[vertex] = index
lowlinks[vertex] = index
index += 1
stack.append(vertex)
for v, w in (e for e in edges if e[0] == vertex):
if indices[w] < 0:
strong_connect(w)
lowlinks[v] = min(lowlinks[v], lowlinks[w])
elif w in stack:
lowlinks[v] = min(lowlinks[v], indices[w])
if indices[vertex] == lowlinks[vertex]:
connected_components.append([])
while stack[-1] != vertex:
connected_components[-1].append(stack.pop())
connected_components[-1].append(stack.pop())
edges = [('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'E'), ('E', 'A'), ('A', 'E'), ('C', 'A'), ('C', 'E'), ('D', 'F'), ('F', 'B'), ('E', 'F')]
vertices = set(v for v in itertools.chain(*edges))
indices = dict((v, -1) for v in vertices)
lowlinks = indices.copy()
connected_components = []
index = 0
stack = []
for v in vertices:
if indices[v] < 0:
strong_connect(v)
print(connected_components)
答案 1 :(得分:2)
看起来您的图是无向的,这意味着,对于任何两个节点A和B,如果存在从A到B的边,则从B到A有一条边。要查找图的连通分量,你可以简单地使用depth-first search。从任何节点开始并跟随边缘,直到您无法访问任何更多节点而不会出现重复项。这是第一个连接的组件。然后从尚未触及的任何节点开始并重复。当你到达图表中的所有节点时就完成了。
答案 2 :(得分:2)
如果你要做很多图形工作并且不想要使用Sage的开销,我只需安装networkx:
>>> import networkx as nx
>>>
>>> nodes_and_edges = {67: [68, 332], 68: [67], 265: [266],
... 266: [265], 332: [67, 333], 333: [332, 334],
... 334: [333, 335], 335: [334, 336], 336: [335]}
>>>
>>> G = nx.Graph(nodes_and_edges)
>>> G
<networkx.classes.graph.Graph object at 0x11ac510>
>>> nx.connected_components(G)
[[67, 68, 332, 333, 334, 335, 336], [265, 266]]