일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- DP
- KMP
- 2-sat
- Floyd
- IndexedTree
- Bellman-Ford
- LCA
- Union-Find
- Sweeping
- ArticulationPoint
- DFS
- Math
- TwoPointers
- Implementation
- greedy
- SlidingWindow
- LIS
- ShortestPath
- Dijkstra
- Bridge
- backtracking
- Flow
- MST
- topologicalsort
- FenwickTree
- Tree
- BFS
- scc
- mergesorttree
- BinarySearch
- Today
- Total
정리충의 정리노트
[백준] 5719: 거의 최단 경로 (수정) 본문
0. 문제 주소
https://www.acmicpc.net/problem/5719
5719번: 거의 최단 경로
문제 요즘 많은 자동차에서는 GPS 네비게이션 장비가 설치되어 있다. 네비게이션은 사용자가 입력한 출발점과 도착점 사이의 최단 경로를 검색해 준다. 하지만, 교통 상황을 고려하지 않고 최단 경로를 검색하는 경우에는 극심한 교통 정체를 경험할 수 있다. 상근이는 오직 자기 자신만 사용 가능한 네비게이션을 만들고 있다. 이 네비게이션은 절대로 최단 경로를 찾아주지 않는다. 항상 거의 최단 경로를 찾아준다. 거의 최단 경로란 최단 경로에 포함되지 않는 도로로만
www.acmicpc.net
1. 풀이
최단 경로가 여러개일 수 있고, 그 여러 최단 경로끼리도 간선을 공유할 수 있다.
풀이는 다음과 같다.
0. 문제에서 주어지는 방향 간선으로 그래프를 만들고, 그 역방향 간선으로 별도의 그래프를 만들어 둔다.
1. 다익스트라 알고리즘을 적용한다.
2. 도착점에서부터 역방향 간선으로 만든 그래프를 순회하며, 현재의 노드를 curr, 다음 노드를 next, 가중치를 weight이라고 하면, dist[curr] - weight = dist[next]를 만족하는 경우 (next, curr) 간선은 최단 경로에 포함되는 간선이다.
역방향으로 BFS 순회를 할 때 이미 최단 경로에 포함되었다고 확인했던 간선이면 continue 해주어야 한다. (Line 85) 재채점돼서 MLE 떴다가 다시 AC 띄우는데 고생함 ㅠ
3. 이를 avail 배열에 저장한다. ( avail[i][j] = (i, j) 간선이 최단 경로에 포함되는 경우 true)
4. 다시 한번 다익스트라를 적용하되 최단 경로에 포함된 경우 그 간선은 이용하지 않는다.
2. 풀이 코드
* 유의할 점
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#define pii pair<int, int>
#define MAX 503
#define INF 987654321
using namespace std;
int N, M, S, D;
int dist[MAX];
bool available[MAX][MAX]; // available[i][j] = i -> j로 가는 간선은 최단 경로에 포함됨.
bool visited[MAX];
vector<pii> graph[MAX];
vector<pii> rev_graph[MAX];
int main(){
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
while(1){
scanf("%d %d", &N, &M);
if (N==0 && M==0) break;
for (int i=0;i<N;i++){
dist[i] = INF;
}
memset(visited, 0, sizeof(visited));
memset(available, 0, sizeof(available));
for (int i=0;i<N;i++){
graph[i].clear();
rev_graph[i].clear();
}
priority_queue<pii, vector<pii>, greater<pii>> PQ;
scanf("%d %d", &S, &D);
for (int i=0;i<M;i++){
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
graph[u].push_back(pii(v, w));
rev_graph[v].push_back(pii(u, w));
}
dist[S] = 0;
PQ.push(pii(0, S));
while(!PQ.empty()){
auto p = PQ.top();
PQ.pop();
int curr = p.second, curr_dist = p.first;
if (dist[curr] < curr_dist) continue;
// visited[curr] = true;
for (auto pp: graph[curr]){
int next = pp.first, weight = pp.second;
if (dist[next] > curr_dist + weight){
dist[next] = curr_dist + weight;
PQ.push(pii(dist[next], next));
}
}
}
if (dist[D] == INF) {
printf("-1\n");
continue;
}
queue<pii> Q;
Q.push(pii(D, dist[D]));
while(!Q.empty()){
auto pp = Q.front();
int curr = pp.first, curr_remain = pp.second;
Q.pop();
if (curr == S) continue;
for (auto ppp: rev_graph[curr]){
int next = ppp.first, weight = ppp.second;
if (available[next][curr]) continue;
if (curr_remain - weight == dist[next]){
available[next][curr] = true;
Q.push(pii(next, dist[next]));
}
}
}
// for (int i=0;i<N;i++){
// for (int j=0;j<N;j++){
// printf("%d ", available[i][j]);
// }
// printf("\n");
// }
// printf("\n");
for (int i=0;i<N;i++){
dist[i] = INF;
}
// memset(visited, 0, sizeof(visited));
dist[S] = 0;
PQ.push(pii(0, S));
while(!PQ.empty()){
auto p = PQ.top();
PQ.pop();
int curr = p.second, curr_dist = p.first;
if (dist[curr] < curr_dist) continue;
// visited[curr] = true;
for (auto pp: graph[curr]){
int next = pp.first, weight = pp.second;
if (!available[curr][next] && dist[next] > curr_dist + weight){
dist[next] = curr_dist + weight;
PQ.push(pii(dist[next], next));
}
}
}
if (dist[D] == INF) printf("-1\n");
else printf("%d\n", dist[D]);
}
return 0;
}
'PS > ShortestPath' 카테고리의 다른 글
[백준] 9323: 무임승차 (0) | 2020.03.10 |
---|---|
[백준] 2982: 국왕의 방문 (0) | 2020.03.07 |
[백준] 2211: 네트워크 복구 (0) | 2020.03.07 |
[백준] 9370: 미확인 도착지 (0) | 2020.03.07 |
[백준] 3860: 할로윈 묘지 (0) | 2020.02.21 |