Intro
이 알고리즘은 그래프에서 node A에서 B까지의 최단 경로를 구한다. 이 때 최단 경로란 시작 점부터 끝 점까지 이동하는 동안 거치는 가중치의 합이 최소가 되도록 하는 경로를 말한다. 가중치가 있는 그래프에서 5-10 으로 도착하는 것보다 1-2-3으로 도착하는 것이 더 최단 경로라고 할 수 있다. 만약 가중치가 없는 그래프에서는 BFS를 이용해 두 노드 사이의 최단 거리를 구하면 그것이 곧 최단 경로 탐색이 된다.
그래프,BFS 알고리즘 : maru20564.tistory.com/6
대표적인 그래프 탐색 알고리즘 DFS/BFS 이론
Before 그래프(Graph) Node와 그 노드(or vertex)간의 선(edge)으로 이루어진 자료 구조를 의미함. Tree 도 Graph의 일종. Node는 그 안에 value가 있다. 여려 value가 있을 수도 있다. 주로 node를 구분하기 위한..
maru20564.tistory.com
만약 가중치가 있는 그래프에서 최단 경로 탐색을 할 때 쓰는 알고리즘 중 하나로 가장 알려진 것은 다익스트라 알고리즘이다.
Dijkstra
다익스트라 알고리즘은 시작 노드에서 가장 최단 거리가 짧은 노드를 차례때로 선택하여 거리를 계산해나가는 알고리즘이다.
- 시작 노드 A를 기준으로 나머지 노드는 모두 미방문으로 초기화한다. 그리고 현재 연결되지 않은 값은 거리가 무한대이다.
- 시작 노드는 방문하며 거리가 0으로 시작한다.
- 아직 방문하지 않은 노드 중 A노드까지 가는 weight가 가장 짧은 노드를 탐색한다.
- A 노드에서 해당 노드까지 방문한 가중치의 합을 통해 해당 노드까지의 거리를 업데이트한다. 서로 비교하여 최소 weight만 남긴다.
- 모든 노드를 방문할 때까지 방문하면 최종 B노드까지의 최소 weight path를 구할 수 있다.
해당 알고리즘을 C++로 구현하면 다음과 같다.
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
int dijkstra(vector<vector<pair<int, int>>> graph,int n, int start, int end) {
if(start == end)
return 0;
//초기화
int INF = 100000;
int* dist = new int[n + 1]; //그래프 저장 때 0은 사용 안했기 때문에 +1
bool* check = new bool[n + 1];
bool end_check = false;
for (int i = 1; i < n + 1; i++) {
dist[i] = INF;
check[i] = false;
}
//첫 노드와 그에 연결된 노드 업데이트
dist[start] = 0;
check[start] = true;
for (int i = 0; i < graph[start].size(); i++)
dist[graph[start][i].first] = graph[start][i].second; //첫 노드와 연결된 가중치 == distance
while (!end_check) {
//min distance를 찾아 방문한다.
int min_distance = INF;
int min_node = -1;
for (int i = 1; i < n + 1; i++) {
if (check[i] == false && dist[i] != INF) {
if (dist[i] < min_distance) {
min_distance = dist[i];
min_node = i;
}
}
}
//min distance 노드를 방문한 후 해당 노드와 연결되어있는 노드들의 start 노드까지의 가중치를 업데이트 한다.
check[min_node] = true;
for (int i = 0; i < graph[min_node].size(); i++) {
//값이 더 작아질 때만 업데이트
if(dist[graph[min_node][i].first] > dist[min_node] + graph[min_node][i].second)
dist[graph[min_node][i].first] = dist[min_node] + graph[min_node][i].second;
}
//end check
end_check = true;
for (int i = 1; i < n + 1; i++) {
if (check[i] == false)
end_check = false;
}
}
int res = dist[end];
delete[] dist;
delete[] check;
return res;
}
int main(void)
{
int n, m;
cin >> n >> m; // node edge의 개수를 입력받음
//graph 생성
vector<vector<pair<int,int>>> graph;
vector<pair<int,int>> edge;
for (int i = 0; i < n + 1; i++) //index 0은 사용 안함. node 번호 1부터 시작.
graph.push_back(edge);
//edge 입력
for (int i = 0; i < m; i++) {
int u, v, w; //u 해당 노드, v 연결되는 노드, w 가중치
cin >> u >> v >> w;
//vertax 중복 예외처리
for (int i = 0; i < graph[u].size(); i++) {
if (graph[u][i].first == v) {
graph[u].erase(graph[u].begin() + i);
break;
}
}
graph[u].push_back(make_pair(v, w));
//양방향일 때
for (int i = 0; i < graph[v].size(); i++) {
if (graph[v][i].first == u) {
graph[v].erase(graph[v].begin() + i);
break;
}
}
graph[v].push_back(make_pair(v, w));
}
int start, end, res;
cout << "input start and end" << endl;
cin >> start >> end;
//예외처리
if (start < 0 || start > n || end < 0 || end > n)
return 1;
res = dijkstra(graph, n, start, end);
cout << res;
return 0;
}
그래프 구현은 전에 그래프 때 만들었던 방식대로 vector를 사용한 인접 리스트 방식으로 거기에 weight를 추가하여 구현하였다. weight는 pair를 사용하여 붙여두었다.
- 실행 결과
간단 그래프 예시에 가중치를 붙여 최단 경로 가중치를 계산해 보았다. 그 결과는 다음과 같다.

만약 DFS/BFS처럼 해당 노드까지의 최단 경로 path를 알고 싶으면 다익스트라 알고리즘에 추가하여 응용하면 된다.
'알고리즘 공부' 카테고리의 다른 글
| C++ 이진탐색 정리, 코드 (0) | 2021.04.11 |
|---|---|
| C++ 정렬(Sorting) 알고리즘 정리(2) - 코드, 프로그램 수행 시간 측정 (0) | 2021.04.08 |
| C++ 정렬(Sorting) 알고리즘 정리(1) - 이론 (0) | 2021.04.07 |
| C++ 그래프 탐색 알고리즘 기본 DFS/BFS 구현 (0) | 2021.04.07 |
| 대표적인 그래프 탐색 알고리즘 DFS/BFS 이론 (0) | 2021.04.07 |
댓글