yuribの答えについてもう少し詳しく説明すると、私は次のようなことをします(igraphメーリングリストにも投稿されています)。
2つの属性を使用します。1つは頂点用で、もう1つはエッジ用です。edge属性は単純で、呼び出され、探している値cut_value
であるか、その値が含まれています。None
最初は、これらの値はすべてNone
sです。cut_value=None
未処理のエッジと、``cut_valueがNone```で処理されていないエッジを呼び出します。
頂点属性はと呼ばれcut_size
、未処理の入射エッジが1つだけ存在する頂点に対してのみ有効です。ツリーがあるので、すべてのエッジが処理されない限り(アルゴリズムを終了できる場合)、常に少なくとも1つのそのような頂点があります。最初は、cut_size
すべての頂点に対して1になります(ただし、未処理の入射エッジが1つだけある頂点に対してのみ有効であることを忘れないでください)。
deg
また、特定のノードで発生した未処理のエッジの数を含むリストもあります。最初はすべてのエッジが未処理であるため、このリストには頂点の次数が含まれています。
これまでのところ、これがあります:
n, m = graph.vcount(), graph.ecount()
cut_values = [None] * m
cut_sizes = [1] * n
deg = graph.degree()
常に、1つのインシデントの未処理のエッジを持つ頂点を処理します。最初に、これらをキューに入れます。
from collections import deque
q = deque(v for v, d in enumerate(deg) if d == 1)
次に、キューが空になるまで、キュー内の頂点を次のように1つずつ処理します。
まず、キューから頂点vを削除し、未処理の唯一のインシデントエッジを見つけます。このエッジをeで表すとします
eのはcut_value
、eの重みに。を掛けたものです。min(cut_size[v], n - cut_size[v])
eのもう一方の端点をuで表すとします。eが処理されるようになったため、 uに入射する未処理のエッジの数が1つ減少したため、1つ減らす必要がありdeg[u]
ます。1になると、 uをキューdeg[u]
に入れます。また、 vはグラフの一部であり、後でuに入射する最後のエッジを削除するときに分離されるため、これも1つ増やします。cut_size
Pythonでは、これは次のコードのようになります(テストされていません)。
weights = graph.es["weight"]
while q:
# Step 1
v = q.popleft()
neis = [e for e in graph.incident(v) if cut_value[e] is None]
if len(neis) != 1:
raise ValueError("this should not have happened")
e = neis[0]
# Step 2
cut_values[e] = weights[e] * min(cut_sizes[v], n - cut_sizes[v])
# Step 3
endpoints = graph.es[e].tuple
u = endpoints[1] if endpoints[0] == v else endpoints[0]
deg[u] -= 1
if deg[u] == 1:
q.append(u)
cut_sizes[u] += 1