가장 짧 은 경 로 를 구 하 는 세 가지 알고리즘: Ford, Dijkstra 와 Floyd
Bellman - ford 는 이해 하기 쉬 운 단원 최 단 경로 알고리즘 으로 Bellman - ford 알고리즘 은 두 개의 배열 이 보조 해 야 합 니 다.
dis[i]
: 정점 i 에서 원점 까지 최 단 경 로 를 알 고 있 습 니 다 path[i]
: 정점 i 를 원점 에서 알 고 있 는 가장 짧 은 경로 에 저장 하고 i 의 앞 정점. Ford 알고리즘 은 매번 모든 변 을 반복 하고 변 을 이완 (relax) 합 니 다. 변 e 를 이완 시 키 는 것 은 원점 에서 e. start 를 통 해 e. stop 에 도착 하 는 경로 가 가장 짧 은 경로 보다 길 면 가장 짧 은 경 로 를 업데이트 하 는 것 을 말 합 니 다.
설명 하기 편리 하도록 본 고 는 python 실현 알고리즘 을 사용 합 니 다. 먼저 두 개의 도구 함 수 를 실현 합 니 다.
INF = 1e6
def make_mat(m, n, fill=None):
mat = []
for i in range(m):
mat.append([fill] * n)
return mat
def get_edges(graph):
n = len(graph)
edges = []
for i in range(n):
for j in range(n):
if graph[i][j] != 0:
edges.append((i, j, graph[i][j]))
return edges
make_mat
2 차원 배열 을 초기 화 하 는 데 사 용 됩 니 다. get_edges
그림 을 인접 행렬 에서 변 경 된 목록 으로 표시 하 는 데 사 용 됩 니 다.다음은 Bellman - ford 알고리즘 을 실현 할 수 있 습 니 다.
def ford(graph, v0):
n = len(graph)
edges = get_edges(graph)
dis = [INF] * n
dis[v0] = 0
path = [0] * n
for k in range(n-1):
for edge in edges:
# relax
if dis[edge[0]] + edge[2] < dis[edge[1]]:
dis[edge[1]] = dis[edge[0]] + edge[2]
path[edge[1]] = edge[0]
return dis, path
초기 화 후 교체 와 이완 작업 을 수행 하 는 것 은 매우 간단 합 니 다.
path [i] 에서 가장 짧 은 경로 의 전구 정점 을 얻 고 정점 i 에서 원점 까지 의 가장 짧 은 경 로 를 차례로 교체 합 니 다. 거꾸로 하면 원점 에서 i 까지 의 가장 짧 은 경 로 를 얻 을 수 있 습 니 다.
def show(path, start, stop):
i = stop
tmp = [stop]
while i != start:
i = path[i]
tmp.append(i)
return list(reversed(tmp))
Ford 알고리즘 은 경로 의 값 을 마이너스 로 허용 합 니 다. 그러나 경로 에 총 값 이 마이너스 인 링 이 존재 하면 이 링 을 통과 할 때마다 가장 짧 은 경로 의 길이 가 줄 어 듭 니 다. 따라서 그림 의 일부 점 은 가장 짧 은 경로 (최 단 경로 의 길 이 는 마이너스 무한) 가 존재 하지 않 습 니 다.
만약 경로 에 마이너스 고리 가 존재 하지 않 는 다 면 n - 1 차 교체 후 느슨 해 질 수 있 는 변 이 존재 하지 않 습 니 다. 따라서 한 번 더 사 이 드 를 옮 겨 다 니 며 느슨 해 질 수 있 는 변 설명 그림 에 마이너스 고리 가 존재 합 니 다.
이렇게 개선 하면 네 거 티 브 링 을 감지 할 수 있 는 Ford 알고리즘 을 얻 을 수 있 습 니 다.
def ford(graph, v0):
n = len(graph)
edges = get_edges(graph)
dis = [INF] * n
dis[v0] = 0
path = [0] * n
for k in range(n-1):
for edge in edges:
# relax
if dis[edge[0]] + edge[2] < dis[edge[1]]:
dis[edge[1]] = dis[edge[0]] + edge[2]
path[edge[1]] = edge[0]
# check negative loop
flag = False
for edge in edges:
# try to relax
if dis[edge[0]] + edge[2] < dis[edge[1]]:
flag = True
break
if flag:
return False
return dis, path
Dijkstra 알고리즘 은 욕심 산법 이지 만 전체 국면 에서 가장 좋 은 해 를 구 할 수 있 습 니 다. Dijkstra 알고리즘 은 Ford 알고리즘 과 같은 두 개의 보조 배열 이 필요 합 니 다.
dis[i]
: 정점 i 에서 원점 까지 최 단 경 로 를 알 고 있 습 니 다 path[i]
: 정점 i 를 원점 에서 알 고 있 는 가장 짧 은 경로 에 저장 하고 i 의 앞 정점. def dijkstra(graph, v0):
n = len(graph)
dis = [INF] * n
dis[v0] = 0
path = [0] * n
unvisited = get_edges(graph)
heapq.heapify(unvisited)
while len(unvisited):
u = heapq.heappop(unvisited)[1]
for v in range(len(graph[u])):
w = graph[u][v]
if dis[u] + w < dis[v]:
dis[v] = dis[u] + w
path[v] = u
return dis, path
floyd 알고리즘 은 동적 계획 사상의 다 원 최 단 경로 알고리즘 을 사용 합 니 다. 똑 같이 두 개의 보조 배열 이 필요 하지만 다 원 최 단 경로 알고리즘 으로서 그 구조 가 다 릅 니 다.
dis[i][j]
: 정점 i 에서 정점 j 까지 알려 진 최 단 경 로 를 저장 하고 직접 연결 로 초기 화 합 니 다 path[i][j]
: 정점 i 에서 정점 j 까지 알려 진 가장 짧 은 경 로 를 저장 하고 j def floyd(graph):
# init
m = len(graph)
dis = make_mat(m, m, fill=0)
path = make_mat(m, m, fill=0)
for i in range(m):
for j in range(m):
dis[i][j] = graph[i][j]
path[i][j] = j
for k in range(m):
for i in range(m):
for j in range(m):
# relax
if dis[i][k] + dis[k][j] < dis[i][j]:
dis[i][j] = dis[i][k] + dis[k][j]
path[i][j] = path[i][k]
return dis, path
알고리즘 핵심 은 정점 k, i, j 를 옮 겨 다 니 는 것 입 니 다. 정점 i 에서 정점 k 를 거 쳐 정점 j 에 도착 하 는 경 로 는 이미 알 고 있 는 i 에서 j 까지 의 최 단 경로 보다 짧 으 면 이미 알 고 있 는 최 단 경 로 를 업데이트 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.