일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 그래프
- union find
- binary search
- 다익스트라
- Dijkstra
- DP
- SQL
- 이진탐색
- MYSQL
- Two Points
- String
- Brute Force
- two pointer
- Hash
- Stored Procedure
- 스토어드 프로시저
- Trie
Archives
- Today
- Total
codingfarm
Dijkstra, Bellman-Ford, Floyd-Warshall 본문
Algorithm & Data structure/이론
Dijkstra, Bellman-Ford, Floyd-Warshall
scarecrow1992 2021. 4. 20. 18:10
다익스트라
예제
BFS와 유사한 형태지만, BFS는 이미 지나간 노드는 새로운 진입을 철저히 막는 반면
다익스트라는 새로 들어온 진입으로의 경로가 기존의 값보다 더 낫다면 새로운 진입이 가능해진다.
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
|
#include<iostream>
#include<vector>
#define INF 2000000000
using namespace std;
vector<vector<int>> bridges; // bridges[i] : i번 노드에서 이동가능한 노드 목록
vector<vector<int>> weights;
vector<int> distances, predecessor;
int main(void) {
int n, k;
cin >> n >> k;
bridges.assign(n, vector<int>(0, INF));
weights.assign(n, vector<int>(0, INF));
distances.assign(n, INF);
predecessor.assign(n, INF);
int from, to, weight;
for (int i = 0; i < k; i++) {
cin >> from >> to >> weight;
from--, to--;
bridges[from].push_back(to);
weights[from].push_back(weight);
}
distances[0] = 0;
for (int i = 0; i < n; i++) {
for (int node = 0; node < n; node++) {
for (int j = 0; j < bridges[node].size(); j++) {
int next = bridges[node][j];
int weight = weights[node][j];
if (distances[node] != INF && distances[next] > distances[node] + weight) {
distances[next] = distances[node] + weight;
predecessor[next] = node;
}
}
}
}
return 0;
}
/*
5 9
1 2 3
1 3 8
1 5 -4
2 4 1
2 5 7
3 2 4
4 1 2
4 3 -5
5 4 6
*/
|
cs |
벨만포드
ratsgo.github.io/data%20structure&algorithm/2017/11/27/bellmanford/
벨만포드는 음의 사이클이 존재하면 사용할 수 없는 알고리즘인데, 이를 역으로 활용하여 음의 사이클의 존재 여부를 확인할 수 있다.
플로이드 워셜
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
|
#include<iostream>
#include<vector>
#include<stack>
#include<string>
#define INF 2000000000
using namespace std;
// inbounds[a][b] : a에서 b 노드로 최단경로로 이동할때 b노드로 들어오게 되는 노드 번호
vector<vector<int>> inbounds;
// dis[a][b] : a에서 b로 가기위한 최저가중치
vector<vector<int>> dist;
void FloydWarshall() {
int N = inbounds.size();
for (int term = 0; term < N; term++) {
for (int to = 0; to < N; to++) {
for (int from = 0; from < N; from++) {
if (dist[from][term] != INF && dist[term][to] != INF) {
if (dist[from][to] > dist[from][term] + dist[term][to]) {
dist[from][to] = dist[from][term] + dist[term][to];
inbounds[from][to] = inbounds[term][to];
}
}
}
}
}
}
void PringBoard(string title, vector<vector<int>>& board) {
cout << title << endl;
for (int row = 0; row < board.size(); row++) {
for (int col = 0; col < board[0].size(); col++) {
cout << board[row][col] << " ";
}
cout << endl;
}
cout << endl;
}
stack<int> GetPath(int from, int to) {
int term;
stack<int> st;
if (from == to) {
cout << endl;
return st;
}
st.push(to);
while (1) {
to = inbounds[from][to];
st.push(to);
if (from == to)
break;
}
while (!st.empty()) {
cout << st.top() << " - ";
st.pop();
}
cout << endl;
return st;
}
int main(void) {
int n;
cin >> n;
inbounds.assign(n, vector<int>(n, INF));
dist.assign(n, vector<int>(n, INF));
for (int i = 0; i < n; i++) {
inbounds[i][i] = INF;
dist[i][i] = 0;
}
int k;
cin >> k;
int from, to, weight;
for (int i = 0; i < k; i++) {
cin >> from >> to >> weight;
from--, to--;
// inbounds[from][to] = from;
//dist[from][to] = weight;
if (dist[from][to] > weight) {
dist[from][to] = weight;
inbounds[from][to] = from;
}
}
PringBoard("dist", dist);
PringBoard("inounds", inbounds);
FloydWarshall();
PringBoard("dist", dist);
PringBoard("inounds", inbounds);
for(int from = 0; from < n; from++)
for (int to = 0; to < n; to++) {
cout << from << "에서 " << to << "까지의 경로 : ";
GetPath(from, to);
}
return 0;
}
/*
5 9
1 2 3
1 3 8
1 5 -4
2 4 1
2 5 7
3 2 4
4 1 2
4 3 -5
5 4 6
*/
|
cs |
'Algorithm & Data structure > 이론' 카테고리의 다른 글
충돌 여부 검사 (0) | 2021.04.21 |
---|---|
정렬된 데이터를 이진탐색으로 슬라이싱 하기(lower_bound, upper_bound) (0) | 2021.04.21 |
비트연산 (0) | 2021.04.19 |
완탐 (0) | 2021.04.19 |
트라이 알고리즘 (trie) (0) | 2021.03.17 |
Comments