Finding Longest Path In A Graph
Solution 1:
You can use a defaultdict
to create your "Graph" from your list of edges/paths:
edges = [['1', '2'], ['2', '4'], ['1', '11'], ['4', '11']]
G = defaultdict(list)
for (s,t) in edges:
G[s].append(t)
G[t].append(s)
print G.items()
Output:
[ ('1', ['2', '11']), ('11', ['1', '4']), ('2', ['1', '4']), ('4', ['2', '11']) ]
Note that I added the edges in both directions, since you're working with an undirected graph. So with the edge (a,b), G[a]
will include b
and G[b]
will include a
.
From this, you can use an algorithm like depth-first search or breadth-first search to discover all the paths in the graph.
In the following code, I used DFS:
defDFS(G,v,seen=None,path=None):
if seen isNone: seen = []
if path isNone: path = [v]
seen.append(v)
paths = []
for t in G[v]:
if t notin seen:
t_path = path + [t]
paths.append(tuple(t_path))
paths.extend(DFS(G, t, seen[:], t_path))
return paths
Which you can use with:
G = defaultdict(list)
for (s,t) in edges:
G[s].append(t)
G[t].append(s)
print DFS(G, '1')
Output:
[('1', '2'), ('1', '2', '4'), ('1', '2', '4', '11'), ('1', '11'), ('1', '11', '4'), ('1', '11', '4', '2')]
So the full code, with the final bit that shows the longest path:
from collections import defaultdict
defDFS(G,v,seen=None,path=None):
if seen isNone: seen = []
if path isNone: path = [v]
seen.append(v)
paths = []
for t in G[v]:
if t notin seen:
t_path = path + [t]
paths.append(tuple(t_path))
paths.extend(DFS(G, t, seen[:], t_path))
return paths
# Define graph by edges
edges = [['1', '2'], ['2', '4'], ['1', '11'], ['4', '11']]
# Build graph dictionary
G = defaultdict(list)
for (s,t) in edges:
G[s].append(t)
G[t].append(s)
# Run DFS, compute metrics
all_paths = DFS(G, '1')
max_len = max(len(p) for p in all_paths)
max_paths = [p for p in all_paths iflen(p) == max_len]
# Outputprint("All Paths:")
print(all_paths)
print("Longest Paths:")
for p in max_paths: print(" ", p)
print("Longest Path Length:")
print(max_len)
Output:
All Paths: [('1', '2'), ('1', '2', '4'), ('1', '2', '4', '11'), ('1', '11'), ('1', '11', '4'), ('1', '11', '4', '2')] Longest Paths: ('1', '2', '4', '11') ('1', '11', '4', '2') Longest Path Length: 4
Note, the "starting point" of your search is specified by the second argument to the DFS
function, in this case, it's '1'
.
Update: As discussed in the comments the above code assumes you have a starting point in mind (specifically the code uses the node labelled '1'
).
A more general method, in the case that you have no such starting point, would be to perform the search starting at every node, and take the overall longest. (Note: In reality, you could be smarter than this)
Changing the line
all_paths = DFS(G, '1')
to
all_paths = [p forpsin [DFS(G, n) forninset(G)] forpin ps]
would give you the longest path between any two points.
(This is a silly list comprehension, but it allows me to update only a single line. Put more clearly, it's equivalent to the following:
all_paths = []
for node in set(G.keys()):
for path in DFS(G, node):
all_paths.append(path)
or
from itertools importchainall_paths= list(chain.from_iterable(DFS(G, n) for n in set(G)))
).
Solution 2:
Here is my code which works for the input in the example but if I tweak the input a little bit, the code fails to give correct number of cities connected.
defdfs(graph, start, visited=None):
if visited isNone:
visited = set()
visited.add(start)
#had to do this for the key error that i was getting if the start doesn't#have any val.ifisinstance(start,str) and start notin graph.keys():
passelse:
fornextinset(graph[start]) - visited:
dfs(graph, next, visited)
return visited
defmaxno_city(input1):
totalcities = []
max_nocity = 0
routedic = {}
#dup = []
rou = []
for cities in input1:
cities = cities.split('#')
totalcities.append(cities)
print (totalcities)
for i in totalcities:
if i[0] in routedic.keys():
routedic[i[0]].append(i[1])
else:
routedic.update({i[0]:[i[1]]})
print(routedic)
keys = routedic.keys()
newkeys = []
for i in keys:
newkeys.append(i)
print (newkeys)
newkeys.sort()
print (newkeys)
expath = dfs(routedic,newkeys[0])
return(len(expath))
The output for the above given input is 4
and I get 4
but If the input is changed to something like this:
['1#2','2#3','1#11','3#11','4#11','4#5','5#6','5#7','6#7','4#12','8#12','9#12','8#10','9#10',8#9]
My code fails.
Thanks, LearningNinja :D
Post a Comment for "Finding Longest Path In A Graph"