単一始点最短距離問題をPythonで解答

負の閉路が存在しない場合、更新はいずれ止まるため、この更新方法で対応できるらしい。

## ベルマンフォード法

class BellmanFord(object):
    def __init__(self, v):
        self.e = 0
        self.d = [float("inf") for i in range(v)]
        self.edge = []

    def append(self, _from, _to, _cost):
        self.edge.append({
            'from': _from, 'to': _to, 'cost': _cost
        })
        self.e = len(self.edge)

    def shortest_path(self, s):
        self.d[s] = 0
        while 1:
            update = True
            for i in range(self.e):
                e = self.edge[i]
                if self.d[e['from']] != float("inf") and self.d[e['to']] > self.d[e['from']] + e['cost']:
                    self.d[e['to']] = self.d[e['from']] + e['cost']
                    update = True
            if update:
                break


## ダイクストラ法

class Dijkstra(object):
    def __init__(self, v):
        self.v = v
        self.e = 0
        self.d = [float("inf") for i in range(v)]
        self.used = [0 for  i in range(v)]
        self.cost = [[float("inf") for i in range(v)] for i in range(v)]

    def append(self, _from, _to, _cost):
        self.cost[_from][_to] = _cost
        self.e += 1

    def shortest_path(self, s):
        self.d[s] = 0
        while 1:
            v = -1

            for u in range(self.v):
                if not self.used[u] and (v == -1 or (self.d[u] < self.d[v])):
                    v = u
            if (v == -1):
                break

            self.used[v] = 1

            for u in range(self.v):
                self.d[u] = min(self.d[u], self.d[v] + self.cost[v][u])
b = BellmanFord(7)
b.append(0, 1, 2)
b.append(1, 0, 2)
b.append(0, 2, 5)
b.append(2, 0, 5)
b.append(1, 2, 4)
b.append(2, 1, 4)
b.append(1, 3, 6)
b.append(3, 1, 6)
b.append(2, 3, 2)
b.append(3, 2, 2)
b.append(1, 4, 10)
b.append(4, 1, 10)
b.append(3, 5, 1)
b.append(5, 3, 1)
b.append(4, 5, 3)
b.append(5, 4, 3)
b.append(4, 6, 5)
b.append(6, 4, 5)
b.append(5, 6, 9)
b.append(6, 5, 9)

b.shortest_path(0)

In [40]: b.d
Out[40]: [0, 2, 5, 7, 11, 8, 16]

In [41]: b.d[6]
Out[41]: 16