반응형

벨만 포드 알고리즘의 코드 구현은 다음 사이트의 내용을 참조하였다.


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;
    graph->= E;
 
    graph->edge = (struct Edge*) malloc(graph->* 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;
    graph->= E;
 
    graph->edge = (struct Edge*) malloc(graph->* 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








반응형