문제 확인
다익스트라 알고리즘을 활용하는 문제입니다.
풀이
방법은 2가지가 있으며 두 방법 모두 비슷한 결과로 나옵니다.
- 1번의 다익스트라 알고리즘을 수행하면서 g-h 간선을 지나는 경우를 체크하는 방법
- start-g + g-h + h-dest 혹은 start-h + h-g + g-dest 가 start-dest와 값이 같은지 확인하는 방법, 3번의 다익스트라 알고리즘을 수행
결과가 비슷한 이유는 기존 다익스트라 알고리즘 계산 시 dist, graph 배열 2가지를 접근하지만 1번 방법의 경우 조건절이 추가되고 check 배열을 추가로 접근해야 하므로 메모리 접근 관점에서 느려질 수 있습니다.
2번 풀이는 다익스트라 알고리즘을 함수로 만들어 간단하게 풀 수 있으므로 1번 방법을 코드로 올리겠습니다.
1번 풀이 시 간선 g-h를 접근하는 경우와 다른 경로를 통해서 오는 경우가 같은 cost를 가질 경우 다익스트라 알고리즘 특성에 의해 문제가 생길 수 있으므로 간선들의 cost 값을 2배 해 주고 g-h 간선의 cost는 1을 빼 주어 예외처리를 할 수 있습니다.
코드
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
|
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
typedef struct edge {
int dest, cost;
bool operator<(const edge &t)const {
return cost > t.cost;
}
edge(int d, int c) :dest(d), cost(c) {};
}edge;
void solve() {
int n, m, t;
cin >> n >> m >> t;
int s, g, h;
cin >> s >> g >> h;
vector<edge> vtx[2001];
int a, b, d;
for (int i = 0; i < m; i++) {
cin >> a >> b >> d;
d <<= 1;//비용 2배
vtx[a].emplace_back(b, d);
vtx[b].emplace_back(a, d);
}
for (auto &t : vtx[g])
if (t.dest == h) --t.cost;//g-h 간선 비용 --
for (auto &t : vtx[h])
if (t.dest == g) --t.cost;//h-g 간선 비용 --
int cand[100];
for (int i = 0; i < t; i++)
cin >> cand[i];
sort(cand, cand + t);
priority_queue <edge, vector<edge>> que;
bool check[2001] = { 0 };
int dist[2001];
memset(dist, 0x7f, sizeof dist);
que.push({ s, 0 });
dist[s] = 0;
while (!que.empty()) {//다익스트라 알고리즘
int cur = que.top().dest, cost = que.top().cost;
auto &cur_vtx = vtx[cur];
que.pop();
for (int i = 0; i < cur_vtx.size(); i++) {
if (dist[cur_vtx[i].dest] > dist[cur] + cur_vtx[i].cost) {
dist[cur_vtx[i].dest] = dist[cur] + cur_vtx[i].cost;
que.push({ cur_vtx[i].dest, dist[cur_vtx[i].dest] });
check[cur_vtx[i].dest] = check[cur];//전 경로의 check 값 상속
if ((cur == g && cur_vtx[i].dest == h) || (cur == h && cur_vtx[i].dest == g))
check[cur_vtx[i].dest] = 1;//경로가 g-h 간선을 지나는 경우 체크
}
}
}
for (int i = 0; i < t; i++) {
if (check[cand[i]])
cout << cand[i] << ' ';
}
}
int main() {
ios_base::sync_with_stdio(0); cin.tie(0);
int T;
cin >> T;
while (T--) {
solve();
cout << '\n';
}
}
|
cs |
반응형
'알고리즘 문제 > [백준]' 카테고리의 다른 글
[백준] 16719 ZOAC (0) | 2021.03.30 |
---|---|
[백준] 19237 어른 상어 (0) | 2021.03.28 |
[백준] 9660 돌 게임 6 (0) | 2021.03.15 |
[백준] 2493 탑 (0) | 2021.03.15 |
[백준] 2836 수상 택시 (0) | 2021.03.09 |