본문 바로가기

프로그래밍/[Algorithm]

[Algorithm] 다익스트라 알고리즘

도착지 까지 최단 거리를 구하는 다익스트라 알고리즘이다.

greedy알고리즘을 통해 구하고 수학적 귀납법을 통해 증명 가능하다.

 

"가정이 방문한 꼭짓점이 n-1일 때 성립한다고 가정하자. 이 경우에, 모든 미방문 꼭짓점에서 dist[u]가 가장 작은 u에 대해서 dist[u] = dist[v] + length[v,u]을 만족하는 변 vu를 선택한다. dist[u]source에서 u까지의 가장 짧은 거리로 볼 수 있다. 만약 그 경로보다 더 짧은 경로가 있고, 그 경로의 첫 번째 미방문 꼭짓점을 w라고 한다면 처음의 가정인 dist[w] > dist[u]에 의해서 모순이 생긴다. 이와 비슷하게, u로 가는 경로 중 미방문 꼭짓점을 지나지 않는 더 짧은 경로가 있고, 그 경로의 마지막 꼭짓점이 w라고 한다면, dist[u] = dist[w] + length[w,u]이여야 하기 때문에 여전히 모순이 생긴다."

 

우선순위 큐를 사용하지 않을 경우  O(V^2)의 복잡도를 가지며(E:edge, V:vertex)

우선순위 큐를 사용할 경우 O(E+VlogV)의 복잡도를 가진다

 

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
#define VERTEX_MAX 50
#define INF 2123456789
 
#include <iostream>
#include <vector>
#include <queue>
#include <fstream>
using namespace std;
 
struct cmp {
    bool operator()(pair<intint> a, pair<intint> b)//우선순위큐 우선순위 정의해주는 함수
    {
        if (a.second > b.second)
            return 1;
        else
        {
            return 0;
        }
    }
};
 
priority_queue<int,vector<pair<int,int>>,cmp> gMyPriorityQueue;
vector<pair<intint>> gVertex[VERTEX_MAX];
 
int gDistance[VERTEX_MAX];
bool gIsVisited[VERTEX_MAX];//우선순위 큐로 할땐 방문체크 안한다.
int gStartVertex;
int gVertexCount;
int gEdgeCount;
 
void fileInput(void);
void printDistance(int* distnace);
void printGraph(vector<pair<intint>>* vertex);
 
 
void fileInput(void)
{
    int tempStartVertex = 0;
    int tempEndVertex = 0;
    int tempWeight = 0;
    ifstream inputFile("graph_input.txt");
    
    inputFile >> gVertexCount;
    inputFile >> gEdgeCount;
    inputFile >> gStartVertex;
 
    for (int i = 0; i < gEdgeCount; i++)
    {
        inputFile >> tempStartVertex;
        inputFile >> tempEndVertex;
        inputFile >> tempWeight;
        gVertex[tempStartVertex].push_back(make_pair(tempEndVertex, tempWeight));        
    }
 
}
 
void printDistance(int* distance)
{
    cout << "distance:" << endl;
    for (int i = 1; i < gVertexCount + 1; i++)
    {
        cout << "d[" << i << "] = " << distance[i] << endl;
    }
}
 
void printGraph(vector<pair<intint>> *vertex)
{
    cout << "vertex:" << endl;
    for (int i = 1; i < gVertexCount+1; i++)
    {
        cout << "[" << i << "]";
        for (vector<pair<intint>>::iterator iter = vertex[i].begin(); iter != vertex[i].end(); ++iter)
        {
            cout << "->";
            cout << (*iter).first << "|" << (*iter).second;
        }
        cout << endl;
    }
}
 
void initGlobals(void)
{
    for (int i = 0; i < gVertexCount+1; i++)
    {
        gDistance[i] = INF;
    }
}
 
void dijkstra(int startVertex)
{
    initGlobals();
    vector<pair<intint>>::iterator edgeIter = gVertex[startVertex].begin();
    gDistance[startVertex] = 0;//자기자신의 weight =0
 
    for (int vertexIndex = 1; vertexIndex < gVertexCount + 1; vertexIndex++)//시작점과 연결된 edge를 넣어준다.
    {
        gMyPriorityQueue.push(make_pair(vertexIndex, gDistance[vertexIndex]));
    }
 
    while (gMyPriorityQueue.empty() == false)
    {
        printDistance(gDistance);
        int currentVertex = 0;
        pair<intint> connectedEdge = make_pair(00);
        if (gDistance[gMyPriorityQueue.top().first] < gMyPriorityQueue.top().second)//오래된 edge들 pop해주는 코드
        {
            gMyPriorityQueue.pop();
            continue;
        }
        currentVertex = gMyPriorityQueue.top().first;
        gMyPriorityQueue.pop();
        for (edgeIter = gVertex[currentVertex].begin(); edgeIter != gVertex[currentVertex].end();++edgeIter)
        {
            connectedEdge = (*edgeIter);
            if (gDistance[currentVertex] + connectedEdge.second < gDistance[connectedEdge.first])
            {
                gDistance[connectedEdge.first] = gDistance[currentVertex] + connectedEdge.second;
            }
            else
            {
                continue;
            }
        }
    }
}
 
int main(void)
{
    fileInput();
    printGraph(gVertex);
    dijkstra(gStartVertex);
    printDistance(gDistance);
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs