Reputation: 1788
I'm not very familiar with the graph theory, but I'll try to explain my problem. I have a dictionnary like this:
{67: [68, 332],
68: [67],
265: [266],
266: [265],
332: [67, 333],
333: [332, 334],
334: [333, 335],
335: [334, 336],
336: [335]}
The keys of this dict are nodes, and the values are edges of the graph. How can we find the connected groups in this graph? [there are two groups - 265->266 and 67->...->366]
Upvotes: 1
Views: 4844
Reputation: 353059
If you're going to be doing a lot of graph stuff and don't want the overhead of using Sage I'd simply install 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]]
Upvotes: 2
Reputation: 14458
It looks like your graph is undirected, meaning that, for any two nodes A and B, if there is an edge from A to B then there is an edge from B to A. To find the connected components of a graph, you can simply use a depth-first search. Start at any node and follow edges until you can't reach any more nodes without hitting duplicates. This is the first connected component. Then start at any node you haven't touched yet and repeat. You're done when you've reached all the nodes in the graph.
Upvotes: 2
Reputation: 150977
I believe you're talking about Tarjan's strongly connected components algorithm.
Here's a Python implementation that I think is correct. You'll have to convert the dictionary to a list of edges, as in [('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)
It's from this question.
Upvotes: 2