を使用しdefaultdict
て、エッジ/パスのリストから「グラフ」を作成できます。
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()
出力:
[
('1', ['2', '11']),
('11', ['1', '4']),
('2', ['1', '4']),
('4', ['2', '11'])
]
無向グラフを使用しているため、両方向にエッジを追加したことに注意してください。したがって、エッジ (a,b) では、G[a]
が含まれb
、G[b]
含まれますa
。
これから、深さ優先検索や幅優先検索などのアルゴリズムを使用して、グラフ内のすべてのパスを検出できます。
次のコードでは、DFS を使用しました。
def DFS(G,v,seen=None,path=None):
if seen is None: seen = []
if path is None: path = [v]
seen.append(v)
paths = []
for t in G[v]:
if t not in seen:
t_path = path + [t]
paths.append(tuple(t_path))
paths.extend(DFS(G, t, seen[:], t_path))
return paths
あなたが使用できるもの:
G = defaultdict(list)
for (s,t) in edges:
G[s].append(t)
G[t].append(s)
print DFS(G, '1')
出力:
[('1', '2'), ('1', '2', '4'), ('1', '2', '4', '11'), ('1', '11 '), ('1', '11', '4'), ('1', '11', '4', '2')]
したがって、最長パスを示す最後のビットを含む完全なコードは次のとおりです。
from collections import defaultdict
def DFS(G,v,seen=None,path=None):
if seen is None: seen = []
if path is None: path = [v]
seen.append(v)
paths = []
for t in G[v]:
if t not in 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 if len(p) == max_len]
# Output
print("All Paths:")
print(all_paths)
print("Longest Paths:")
for p in max_paths: print(" ", p)
print("Longest Path Length:")
print(max_len)
出力:
すべてのパス:
[('1', '2'), ('1', '2', '4'), ('1', '2', '4', '11'), ('1', '11 '), ('1', '11', '4'), ('1', '11', '4', '2')]
最長パス:
('1'、'2'、'4'、'11')
('1'、'11'、'4'、'2')
最長パスの長さ:
4
検索の「開始点」は、DFS
関数の 2 番目の引数によって指定されることに注意してください。この場合は'1'
.
更新: コメントで説明したように、上記のコードは、開始点を念頭に置いていることを前提としています (具体的には、コードは というラベルの付いたノードを使用します'1'
)。
そのような開始点がない場合のより一般的な方法は、すべてのノードから開始して検索を実行し、全体で最も長くかかることです。(注:実際には、これよりも賢いかもしれません)
ラインの変更
all_paths = DFS(G, '1')
に
all_paths = [p for ps in [DFS(G, n) for n in set(G)] for p in ps]
任意の 2 点間の最長パスが得られます。
(これはばかげたリスト内包表記ですが、更新できるのは 1 行だけです。より明確に言えば、次のようになります。
all_paths = []
for node in set(G.keys()):
for path in DFS(G, node):
all_paths.append(path)
また
from itertools import chain
all_paths = list(chain.from_iterable(DFS(G, n) for n in set(G)))
)。