Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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
Archives
Today
Total
관리 메뉴

승형님의 블로그

백준 5719번, 거의 최단 경로 / Almost Shortest Path 본문

Problem Solving/백준

백준 5719번, 거의 최단 경로 / Almost Shortest Path

승형 2022. 11. 24. 21:01

 

https://www.acmicpc.net/problem/5719

 

5719번: 거의 최단 경로

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 장소의 수 N (2 ≤ N ≤ 500)과 도로의 수 M (1 ≤ M ≤ 104)가 주어진다. 장소는 0부터 N-1번까지 번호가 매겨져 있

www.acmicpc.net

요약

 

정점 S에서 정점 D로 가는 최단경로에 포함되지 않은 도로로만 이루어진 그 다음 최단경로를 구한다.


1. 가중치가 존재하는 단방향 그래프가 주어진다.

 

2. 다익스트라를 통해 최단경로와 그 경로를 역추적하여 저장한다.

https://int-p.tistory.com/13

 

다익스트라(Dijkstra) 알고리즘과 최단경로 역추적

다익스트라 알고리즘을 활용하여 최단경로를 구할 때, 최단경로의 길이 뿐만 아니라 정확한 경로를 역추적 해야하는 필요성을 느낄 때가 있다. 기본적인 다익스트라 알고리즘은 다음과 같은 과

int-p.tistory.com

 

3. 2번에서 구한 최단경로에 포함된 간선을 전부 제거한다. 이때, 문제 조건에서 임의의 정점 U에서 V로 가는 도로가 최대 한 개이기 때문에, 최단경로에 포함된 두 정점간의 간선을 모두 제거해도 상관 없다.

 

4. 간선의 제거는 이미 존재하는 간선의 가중치를 INF로 변경하는 방식으로 진행하였다. 이때, 이미 제거된 간선이 또 제거되는 것을 방지하기 위해 방문 배열 mark[node]를 관리하며 DFS 형식으로 제거한다.

 

5. 간선의 개수가 최대 $10^{4}$이므로, 최단경로에 포함된 정점의 모든 간선을 검색하며 제거해도 1초 안에 처리 가능하다.

 

6. 간선이 제거된 그래프에서 다익스트라를 다시 한 번 돌려 거의 최대 경로를 구한다.

 

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;

struct cmp {
	bool operator() (pii A, pii B) {
		return A.first > B.first;
	}
};

int N, M, S, D;
vector <pii> graph[501];
int dist[501];
vector <int> path[501];
int mark[501];

void Dijkstra(int start);
void Delete_Path(int node);

int main(void) {
	ios::sync_with_stdio(false);
	cin.tie(0);
	while (1) {
		cin >> N >> M;
		if (N == 0 && M == 0) break;
		cin >> S >> D;
		for (int i = 0; i < N; i++) {
			graph[i].clear();
			path[i].clear();
			mark[i] = 0;
		}
		for (int i = 0; i < M; i++) {
			int U, V, P;
			cin >> U >> V >> P;
			graph[U].push_back({ V,P });
		}
		Dijkstra(S);
		Delete_Path(D);
		Dijkstra(S);
		if (dist[D] == INF) cout << -1 << '\n';
		else cout << dist[D] << '\n';
	}
	return 0;
}

void Dijkstra(int start) {
	for (int i = 0; i < N; i++) dist[i] = INF;
	priority_queue<pii, vector<pii>, cmp> pq;
	pq.push({ 0, start });
	dist[start] = 0;
	while (pq.size()) {
		int now = pq.top().second;
		int val = pq.top().first;
		pq.pop();
		if (dist[now] < val) continue;
		for (int i = 0; i < graph[now].size(); i++) {
			int next = graph[now][i].first;
			int new_val = val + graph[now][i].second;
			if (dist[next] > new_val) {
				dist[next] = new_val;
				path[next].clear();
				path[next].push_back(now);
				pq.push({ new_val, next });
			}
			else if (dist[next] == new_val) path[next].push_back(now);
		}
	}
}

void Delete_Path(int node) {
	if (mark[node] != 0) return;
	mark[node] = 1;
	for (int i = 0; i < path[node].size(); i++) {
		int now = node;
		int prev = path[node][i];
		for (int j = 0; j < graph[prev].size(); j++) {
			if (graph[prev][j].first == now) graph[prev][j].second = INF; // 간선 제거			
		}
		Delete_Path(prev);
	}
}

 

'Problem Solving > 백준' 카테고리의 다른 글

백준 2307번, 도로검문  (0) 2022.11.25
백준 1162번, 도로포장 / Revamping Trails  (0) 2022.11.25
백준 11779번, 최소비용 구하기 2  (0) 2022.11.24
백준 14554번, The Other Way  (0) 2022.11.24
백준 14611번, 월요병  (0) 2022.11.24
Comments