반응형
벨만 포드 알고리즘의 코드 구현은 다음 사이트의 내용을 참조하였다.
http://www.geeksforgeeks.org/dynamic-programming-set-23-bellman-ford-algorithm/
그리고 벨만 포드 알고리즘이 진행되는 과정은 다음 게시물에 수록되어 있다.
http://www.crocus.co.kr/534 :: 벨만 포드 개념
<< 벨만 포드 알고리즘(Bellman-Ford Algorithm) 소스 코드 >>
(음의 가중치로 구성된 사이클이 없는 경우)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> // 간선 구조체 // src = 시작점, dest = 도착점, weight = 가중치 struct Edge { int src, dest, weight; }; // 그래프 구조체 // V :: 정점의 수 E :: 간선의 수 // edge :: 포인터 형식으로 서로 다른 정점을 연결하기 위해 존재 struct Graph { int V, E; struct Edge* edge; }; // V와 E를 통해 정점과 간선의 수를 가진 그래프를 생성한다. struct Graph* createGraph(int V, int E) { struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph)); graph->V = V; graph->E = E; graph->edge = (struct Edge*) malloc(graph->E * sizeof(struct Edge)); return graph; } // 결과를 출력하기 위한 함수 void printArr(int dist[], int n) { printf("Vertex Distance from Source\n"); for (int i = 0; i < n; ++i) dist[i] == INT_MAX ? printf("%d \t\tINF\n", i) : printf("%d \t\t %d\n", i, dist[i]); } // src에서 모든 다른 정점까지의 최단 거리를 찾아주는 BellmanFord 함수이다. // 음의 가중치 까지 적용이 가능하다. void BellmanFord(struct Graph* graph, int src) { int V = graph->V; int E = graph->E; int *dist = (int*)malloc(sizeof(int)*V); // int dist[V+1]과 같다. // 모든 최단 거리를 무한대로 지정해주고, 시작점(src)만 0으로 초기화 한다. for (int i = 0; i < V; i++) dist[i] = INT_MAX; dist[src] = 0; // 벨만 포드 알고리즘 for (int i = 1; i <= V - 1; i++) { for (int j = 0; j < E; j++) { int u = graph->edge[j].src; int v = graph->edge[j].dest; int weight = graph->edge[j].weight; // 정점u가(시작점이) 무한대가 아니고, // 시작점까지의 최단 거리 + 가중치가 도착점의 가중치 // 보다 작을 때 업데이트 해준다. if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) dist[v] = dist[u] + weight; } } // 음의 가중치 때문에 무한히 최단 경로가 작아지는 것이 있다면 // 탐색하여 알려준다. for (int i = 0; i < E; i++) { int u = graph->edge[i].src; int v = graph->edge[i].dest; int weight = graph->edge[i].weight; // if문에서 현재위치 최단거리 + 가중치가 계속해서 더 작아질 경우 // 음의 사이클이 있다고 판단한다. if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) printf("Graph contains negative weight cycle\n"); } printArr(dist, V); return; } int main() { int V = 5; // 정점의 수 int E = 9; // 간선의 수 struct Graph* graph = createGraph(V, E); // 그래프 정보를 입력해준다. graph->edge[0].src = 0; // 0에서 graph->edge[0].dest = 2; // 2로 가는 간선의 graph->edge[0].weight = 1; // 가중치는 1로 정한다. graph->edge[1].src = 0; graph->edge[1].dest = 3; graph->edge[1].weight = 5; graph->edge[2].src = 1; graph->edge[2].dest = 2; graph->edge[2].weight = -2; graph->edge[3].src = 2; graph->edge[3].dest = 1; graph->edge[3].weight = 4; graph->edge[4].src = 2; graph->edge[4].dest = 3; graph->edge[4].weight = 4; graph->edge[5].src = 3; graph->edge[5].dest = 0; graph->edge[5].weight = -1; graph->edge[6].src = 3; graph->edge[6].dest = 1; graph->edge[6].weight = 3; graph->edge[7].src = 4; graph->edge[7].dest = 0; graph->edge[7].weight = 1; graph->edge[8].src = 4; graph->edge[8].dest = 2; graph->edge[8].weight = -1; BellmanFord(graph, 0); return 0; } | Crocus |
결과 값은 다음과 같고, 이 과정에 대한 내용은 http://www.crocus.co.kr/534 에 자세히 수록되어 있다.
(음의 가중치로 구성된 사이클이 있는 경우)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> // 간선 구조체 // src = 시작점, dest = 도착점, weight = 가중치 struct Edge { int src, dest, weight; }; // 그래프 구조체 // V :: 정점의 수 E :: 간선의 수 // edge :: 포인터 형식으로 서로 다른 정점을 연결하기 위해 존재 struct Graph { int V, E; struct Edge* edge; }; // V와 E를 통해 정점과 간선의 수를 가진 그래프를 생성한다. struct Graph* createGraph(int V, int E) { struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph)); graph->V = V; graph->E = E; graph->edge = (struct Edge*) malloc(graph->E * sizeof(struct Edge)); return graph; } // 결과를 출력하기 위한 함수 void printArr(int dist[], int n) { printf("Vertex Distance from Source\n"); for (int i = 0; i < n; ++i) dist[i] == INT_MAX ? printf("%d \t\tINF\n",i) : printf("%d \t\t %d\n", i, dist[i]); } // src에서 모든 다른 정점까지의 최단 거리를 찾아주는 BellmanFord 함수이다. // 음의 가중치 까지 적용이 가능하다. void BellmanFord(struct Graph* graph, int src) { int V = graph->V; int E = graph->E; int *dist = (int*)malloc(sizeof(int)*V); // int dist[V+1]과 같다. // 모든 최단 거리를 무한대로 지정해주고, 시작점(src)만 0으로 초기화 한다. for (int i = 0; i < V; i++) dist[i] = INT_MAX; dist[src] = 0; // 벨만 포드 알고리즘 for (int i = 1; i <= V - 1; i++) { for (int j = 0; j < E; j++) { int u = graph->edge[j].src; int v = graph->edge[j].dest; int weight = graph->edge[j].weight; // 정점u가(시작점이) 무한대가 아니고, // 시작점까지의 최단 거리 + 가중치가 도착점의 가중치 // 보다 작을 때 업데이트 해준다. if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) dist[v] = dist[u] + weight; } } // 음의 가중치 때문에 무한히 최단 경로가 작아지는 것이 있다면 // 탐색하여 알려준다. for (int i = 0; i < E; i++) { int u = graph->edge[i].src; int v = graph->edge[i].dest; int weight = graph->edge[i].weight; // if문에서 현재위치 최단거리 + 가중치가 계속해서 더 작아질 경우 // 음의 사이클이 있다고 판단한다. if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) printf("Graph contains negative weight cycle\n"); } printArr(dist, V); return; } int main() { int V = 5; // 정점의 수 int E = 9; // 간선의 수 struct Graph* graph = createGraph(V, E); // 그래프 정보를 입력해준다. graph->edge[0].src = 0; // 0에서 graph->edge[0].dest = 1; // 1로 가는 간선의 graph->edge[0].weight = -2; // 가중치는 -2로 정한다. graph->edge[1].src = 0; graph->edge[1].dest = 2; graph->edge[1].weight = 5; graph->edge[2].src = 0; graph->edge[2].dest = 3; graph->edge[2].weight = 3; graph->edge[3].src = 1; graph->edge[3].dest = 0; graph->edge[3].weight = -2; graph->edge[4].src = 1; graph->edge[4].dest = 4; graph->edge[4].weight = 4; graph->edge[5].src = 3; graph->edge[5].dest = 1; graph->edge[5].weight = 3; graph->edge[6].src = 4; graph->edge[6].dest = 2; graph->edge[6].weight = 1; graph->edge[7].src = 4; graph->edge[7].dest = 0; graph->edge[7].weight = 1; graph->edge[8].src = 4; graph->edge[8].dest = 3; graph->edge[8].weight = -2; BellmanFord(graph, 0); return 0; } | Crocus |
반응형
'Applied > 알고리즘' 카테고리의 다른 글
플로이드 워셜 알고리즘(Floyd Warshall Algorithm) 소스 코드 (2) | 2016.11.17 |
---|---|
플로이드 워셜 알고리즘(Floyd Warshall Algorithm) 개념 (12) | 2016.11.17 |
벨만 포드 알고리즘(Bellman-Ford Algorithm) 개념 (2) | 2016.11.17 |
다익스트라 알고리즘(Dijkstra Algorithm) 소스 코드 (3) | 2016.11.16 |
다익스트라 알고리즘(Dijkstra Algorithm) 개념 (6) | 2016.11.16 |