본문 바로가기

백준

C++[백준] 5719 거의 최단 경로

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

 

5719번: 거의 최단 경로

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

www.acmicpc.net

 

 

솔루션


처음에는 최단으로 도달 할 수 있는 경로 한개에 대해서만 방문하지 않도록 처리 하였는데, 알고보니, 최단 경로 모두 다 탐색하지 못하도록 하여야 한다.

 

1. 먼저 시작점을 기준으로 다익스트라를 돌리고,

 

2. dfs를 통해서, 특정 경로를 선택해서 목적지에 가중치가 넘지 않고 도달 가능하면 해당 경로를 bool 배열을 통해 true 로 바꿔준다.

 

3. 모든 최단 경로를 true로 바꿔줬다면, 다시 다익스트라를 돌린다. (이 때, 2.의 과정에서 true로 바꾼 경로에 대해서는 탐색하지 않는다.)

 

 

이렇게 하니, AC를 받았다.

 

dfs를 돌릴 때, 예외 처리의 순서가 잘 못 되어서 틀렸습니다를 받았다. 이점 주의!

 

 

 

코드


#define INF 987654321
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

vector<pair<int, int>>V[502];
int N, M;
int dest, start;
bool is_visit[502][1004];


int weight[502];
void dijkstra() {
	
	for (int i = 0; i <= N; i++) weight[i] = INF;

	priority_queue<pair<int, int>> pq;
	pq.push({ 0,start });
	weight[start] = 0;
	
	while (!pq.empty()) {
		int str = pq.top().second;
		int w = -pq.top().first;
		pq.pop();

		if (weight[str] < w) continue;

		for (int i = 0; i < V[str].size(); i++) {
			int next = V[str][i].first;
			int cost = w + V[str][i].second;

			if (is_visit[str][next] || weight[next] <= cost) continue;
			pq.push({ -cost,next });
			weight[next] = cost;
		}
	}
}

//0은 방문 X, 1은 방문을 했지만 경로 X, 2는 방문 했고, 길도 있음.
int is_travel[502];
bool travel(int str, int w) {
	if (w > weight[str]) return false;
	if (str == dest && w == weight[dest]) {
		return true;
	}
	else if (is_travel[str] == 1) {
		return false;
	}
	else if (is_travel[str] == 2) {
		return true;
	}

	is_travel[str] = 1;
	bool is_road = false;
	for (int i = 0; i < V[str].size(); i++) {
		int cost = w + V[str][i].second;
		int next = V[str][i].first;

		bool tmp = travel(next, cost);
		is_visit[str][next] = tmp;
		if (tmp) {
			is_travel[str] = 2;
			is_road = true;
		}
	}
	if (is_road) {
		return true;
	}
	return false;
}

void init() {
	for (int i = 0; i <= N; i++) {
		V[i].clear();
		is_travel[i] = 0;
		for (int j = 0; j <= M; j++) {
			is_visit[i][j] = false;
		}
	}
	return;
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);

	while (true) {

		cin >> N >> M;
		if (N == M && N == 0) return 0;
		cin >> start >> dest;

		init();

		int str, end, w;
		for (int i = 0; i < M; i++) {
			cin >> str >> end >> w;
			V[str].push_back({ end,w });
		}

		dijkstra();
		travel(start, 0);
		dijkstra();

		if (weight[dest] == INF) cout << -1 << "\n";
		else cout << weight[dest] << "\n";
	}
}

'백준' 카테고리의 다른 글

C++[백준]10217번 KCM Travel  (0) 2023.01.03
C++[백준]1162번 도로포장  (0) 2023.01.03
C++[백준]2211번 네트워크 복구  (0) 2022.12.17
C++[백준]10473번 인간 대포  (0) 2022.12.16
C++[백준] 1316번 그룹 단어 체커  (0) 2022.12.16