1/*
2 * ์ต๋จ ๊ฒฝ๋ก (Shortest Path)
3 * Dijkstra, Bellman-Ford, Floyd-Warshall, 0-1 BFS
4 *
5 * ๊ทธ๋ํ์์ ์ ์ ๊ฐ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ๋ ์๊ณ ๋ฆฌ์ฆ์
๋๋ค.
6 */
7
8#include <iostream>
9#include <vector>
10#include <queue>
11#include <climits>
12#include <algorithm>
13
14using namespace std;
15
16const int INF = INT_MAX;
17
18// =============================================================================
19// 1. Dijkstra ์๊ณ ๋ฆฌ์ฆ
20// =============================================================================
21
22vector<int> dijkstra(int n, const vector<vector<pair<int, int>>>& adj, int start) {
23 vector<int> dist(n, INF);
24 priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
25
26 dist[start] = 0;
27 pq.push({0, start});
28
29 while (!pq.empty()) {
30 auto [d, u] = pq.top();
31 pq.pop();
32
33 if (d > dist[u]) continue;
34
35 for (auto [v, w] : adj[u]) {
36 if (dist[u] + w < dist[v]) {
37 dist[v] = dist[u] + w;
38 pq.push({dist[v], v});
39 }
40 }
41 }
42
43 return dist;
44}
45
46// ๊ฒฝ๋ก ๋ณต์
47pair<vector<int>, vector<int>> dijkstraWithPath(int n, const vector<vector<pair<int, int>>>& adj, int start) {
48 vector<int> dist(n, INF);
49 vector<int> parent(n, -1);
50 priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
51
52 dist[start] = 0;
53 pq.push({0, start});
54
55 while (!pq.empty()) {
56 auto [d, u] = pq.top();
57 pq.pop();
58
59 if (d > dist[u]) continue;
60
61 for (auto [v, w] : adj[u]) {
62 if (dist[u] + w < dist[v]) {
63 dist[v] = dist[u] + w;
64 parent[v] = u;
65 pq.push({dist[v], v});
66 }
67 }
68 }
69
70 return {dist, parent};
71}
72
73vector<int> reconstructPath(int start, int end, const vector<int>& parent) {
74 vector<int> path;
75 for (int at = end; at != -1; at = parent[at]) {
76 path.push_back(at);
77 }
78 reverse(path.begin(), path.end());
79
80 if (path[0] != start) {
81 return {}; // ๊ฒฝ๋ก ์์
82 }
83
84 return path;
85}
86
87// =============================================================================
88// 2. Bellman-Ford ์๊ณ ๋ฆฌ์ฆ
89// =============================================================================
90
91struct Edge {
92 int from, to, weight;
93};
94
95pair<vector<int>, bool> bellmanFord(int n, const vector<Edge>& edges, int start) {
96 vector<int> dist(n, INF);
97 dist[start] = 0;
98
99 // n-1๋ฒ relaxation
100 for (int i = 0; i < n - 1; i++) {
101 bool updated = false;
102 for (const auto& e : edges) {
103 if (dist[e.from] != INF && dist[e.from] + e.weight < dist[e.to]) {
104 dist[e.to] = dist[e.from] + e.weight;
105 updated = true;
106 }
107 }
108 if (!updated) break; // ์กฐ๊ธฐ ์ข
๋ฃ
109 }
110
111 // ์์ ์ฌ์ดํด ๊ฒ์ฌ
112 for (const auto& e : edges) {
113 if (dist[e.from] != INF && dist[e.from] + e.weight < dist[e.to]) {
114 return {dist, true}; // ์์ ์ฌ์ดํด ์กด์ฌ
115 }
116 }
117
118 return {dist, false};
119}
120
121// =============================================================================
122// 3. Floyd-Warshall ์๊ณ ๋ฆฌ์ฆ
123// =============================================================================
124
125vector<vector<int>> floydWarshall(int n, vector<vector<int>>& dist) {
126 // dist๋ ์ด๊ธฐ ์ธ์ ํ๋ ฌ (์ฐ๊ฒฐ ์์ผ๋ฉด INF)
127
128 for (int k = 0; k < n; k++) {
129 for (int i = 0; i < n; i++) {
130 for (int j = 0; j < n; j++) {
131 if (dist[i][k] != INF && dist[k][j] != INF) {
132 dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
133 }
134 }
135 }
136 }
137
138 return dist;
139}
140
141// ๊ฒฝ๋ก ๋ณต์ ๊ฐ๋ฅํ ๋ฒ์
142pair<vector<vector<int>>, vector<vector<int>>> floydWarshallWithPath(int n, vector<vector<int>>& dist) {
143 vector<vector<int>> next(n, vector<int>(n, -1));
144
145 // ์ด๊ธฐํ: ์ง์ ์ฐ๊ฒฐ๋ ๊ฒฝ์ฐ
146 for (int i = 0; i < n; i++) {
147 for (int j = 0; j < n; j++) {
148 if (i != j && dist[i][j] != INF) {
149 next[i][j] = j;
150 }
151 }
152 }
153
154 for (int k = 0; k < n; k++) {
155 for (int i = 0; i < n; i++) {
156 for (int j = 0; j < n; j++) {
157 if (dist[i][k] != INF && dist[k][j] != INF &&
158 dist[i][k] + dist[k][j] < dist[i][j]) {
159 dist[i][j] = dist[i][k] + dist[k][j];
160 next[i][j] = next[i][k];
161 }
162 }
163 }
164 }
165
166 return {dist, next};
167}
168
169// =============================================================================
170// 4. 0-1 BFS
171// =============================================================================
172
173vector<int> bfs01(int n, const vector<vector<pair<int, int>>>& adj, int start) {
174 vector<int> dist(n, INF);
175 deque<int> dq;
176
177 dist[start] = 0;
178 dq.push_front(start);
179
180 while (!dq.empty()) {
181 int u = dq.front();
182 dq.pop_front();
183
184 for (auto [v, w] : adj[u]) {
185 if (dist[u] + w < dist[v]) {
186 dist[v] = dist[u] + w;
187 if (w == 0) {
188 dq.push_front(v);
189 } else {
190 dq.push_back(v);
191 }
192 }
193 }
194 }
195
196 return dist;
197}
198
199// =============================================================================
200// 5. SPFA (Shortest Path Faster Algorithm)
201// =============================================================================
202
203pair<vector<int>, bool> spfa(int n, const vector<vector<pair<int, int>>>& adj, int start) {
204 vector<int> dist(n, INF);
205 vector<bool> inQueue(n, false);
206 vector<int> cnt(n, 0); // ํ์ ๋ค์ด๊ฐ ํ์
207 queue<int> q;
208
209 dist[start] = 0;
210 q.push(start);
211 inQueue[start] = true;
212 cnt[start] = 1;
213
214 while (!q.empty()) {
215 int u = q.front();
216 q.pop();
217 inQueue[u] = false;
218
219 for (auto [v, w] : adj[u]) {
220 if (dist[u] + w < dist[v]) {
221 dist[v] = dist[u] + w;
222 if (!inQueue[v]) {
223 q.push(v);
224 inQueue[v] = true;
225 cnt[v]++;
226
227 if (cnt[v] >= n) {
228 return {dist, true}; // ์์ ์ฌ์ดํด
229 }
230 }
231 }
232 }
233 }
234
235 return {dist, false};
236}
237
238// =============================================================================
239// 6. K๋ฒ์งธ ์ต๋จ ๊ฒฝ๋ก
240// =============================================================================
241
242vector<int> kthShortestPath(int n, const vector<vector<pair<int, int>>>& adj,
243 int start, int end, int k) {
244 vector<int> kthDist;
245 vector<int> count(n, 0);
246 priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
247
248 pq.push({0, start});
249
250 while (!pq.empty() && count[end] < k) {
251 auto [d, u] = pq.top();
252 pq.pop();
253
254 count[u]++;
255
256 if (u == end) {
257 kthDist.push_back(d);
258 }
259
260 if (count[u] <= k) {
261 for (auto [v, w] : adj[u]) {
262 pq.push({d + w, v});
263 }
264 }
265 }
266
267 return kthDist;
268}
269
270// =============================================================================
271// ํ
์คํธ
272// =============================================================================
273
274void printVector(const vector<int>& v) {
275 cout << "[";
276 for (size_t i = 0; i < v.size(); i++) {
277 if (v[i] == INF) cout << "โ";
278 else cout << v[i];
279 if (i < v.size() - 1) cout << ", ";
280 }
281 cout << "]";
282}
283
284int main() {
285 cout << "============================================================" << endl;
286 cout << "์ต๋จ ๊ฒฝ๋ก ์์ " << endl;
287 cout << "============================================================" << endl;
288
289 // ํ
์คํธ ๊ทธ๋ํ
290 int n = 5;
291 vector<vector<pair<int, int>>> adj(n);
292 adj[0] = {{1, 4}, {2, 1}};
293 adj[1] = {{3, 1}};
294 adj[2] = {{1, 2}, {3, 5}};
295 adj[3] = {{4, 3}};
296
297 // 1. Dijkstra
298 cout << "\n[1] Dijkstra ์๊ณ ๋ฆฌ์ฆ" << endl;
299 auto dijkDist = dijkstra(n, adj, 0);
300 cout << " 0์์ ๊ฐ ์ ์ ๊น์ง ๊ฑฐ๋ฆฌ: ";
301 printVector(dijkDist);
302 cout << endl;
303
304 // ๊ฒฝ๋ก ๋ณต์
305 auto [dist, parent] = dijkstraWithPath(n, adj, 0);
306 auto path = reconstructPath(0, 4, parent);
307 cout << " 0 โ 4 ๊ฒฝ๋ก: ";
308 printVector(path);
309 cout << " (๊ฑฐ๋ฆฌ: " << dist[4] << ")" << endl;
310
311 // 2. Bellman-Ford
312 cout << "\n[2] Bellman-Ford ์๊ณ ๋ฆฌ์ฆ" << endl;
313 vector<Edge> edges = {
314 {0, 1, 4}, {0, 2, 1}, {1, 3, 1}, {2, 1, 2}, {2, 3, 5}, {3, 4, 3}
315 };
316 auto [bfDist, hasNegCycle] = bellmanFord(n, edges, 0);
317 cout << " 0์์ ๊ฐ ์ ์ ๊น์ง ๊ฑฐ๋ฆฌ: ";
318 printVector(bfDist);
319 cout << endl;
320 cout << " ์์ ์ฌ์ดํด: " << (hasNegCycle ? "์์" : "์์") << endl;
321
322 // 3. Floyd-Warshall
323 cout << "\n[3] Floyd-Warshall ์๊ณ ๋ฆฌ์ฆ" << endl;
324 vector<vector<int>> distMatrix(4, vector<int>(4, INF));
325 for (int i = 0; i < 4; i++) distMatrix[i][i] = 0;
326 distMatrix[0][1] = 3;
327 distMatrix[0][2] = 8;
328 distMatrix[1][2] = 2;
329 distMatrix[2][3] = 1;
330 distMatrix[0][3] = 7;
331
332 floydWarshall(4, distMatrix);
333 cout << " ๋ชจ๋ ์ ์ต๋จ ๊ฑฐ๋ฆฌ:" << endl;
334 for (int i = 0; i < 4; i++) {
335 cout << " " << i << ": ";
336 printVector(distMatrix[i]);
337 cout << endl;
338 }
339
340 // 4. 0-1 BFS
341 cout << "\n[4] 0-1 BFS" << endl;
342 vector<vector<pair<int, int>>> adj01(4);
343 adj01[0] = {{1, 0}, {2, 1}};
344 adj01[1] = {{2, 0}, {3, 1}};
345 adj01[2] = {{3, 0}};
346 auto dist01 = bfs01(4, adj01, 0);
347 cout << " 0์์ ๊ฐ ์ ์ ๊น์ง ๊ฑฐ๋ฆฌ (0-1): ";
348 printVector(dist01);
349 cout << endl;
350
351 // 5. K๋ฒ์งธ ์ต๋จ ๊ฒฝ๋ก
352 cout << "\n[5] K๋ฒ์งธ ์ต๋จ ๊ฒฝ๋ก" << endl;
353 auto kthDists = kthShortestPath(n, adj, 0, 4, 3);
354 cout << " 0 โ 4 ์ 1~3๋ฒ์งธ ์ต๋จ ๊ฑฐ๋ฆฌ: ";
355 printVector(kthDists);
356 cout << endl;
357
358 // 6. ๋ณต์ก๋ ์์ฝ
359 cout << "\n[6] ๋ณต์ก๋ ์์ฝ" << endl;
360 cout << " | ์๊ณ ๋ฆฌ์ฆ | ์๊ฐ๋ณต์ก๋ | ์์ ๊ฐ์ค์น |" << endl;
361 cout << " |------------------|------------------|-------------|" << endl;
362 cout << " | Dijkstra | O((V+E) log V) | X |" << endl;
363 cout << " | Bellman-Ford | O(VE) | O (์ฌ์ดํดX) |" << endl;
364 cout << " | Floyd-Warshall | O(Vยณ) | O (์ฌ์ดํดX) |" << endl;
365 cout << " | 0-1 BFS | O(V + E) | 0,1๋ง |" << endl;
366 cout << " | SPFA | O(VE) ํ๊ท O(E) | O (์ฌ์ดํดX) |" << endl;
367
368 cout << "\n============================================================" << endl;
369
370 return 0;
371}