어흥

[백준 5719] 거의 최단 경로 (C++) 본문

알고리즘/백준

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

라이언납시오 2020. 3. 8. 21:13
728x90
반응형

문제 링크: https://www.acmicpc.net/problem/5719

 

5719번: 거의 최단 경로

문제 요즘 많은 자동차에서는 GPS 네비게이션 장비가 설치되어 있다. 네비게이션은 사용자가 입력한 출발점과 도착점 사이의 최단 경로를 검색해 준다. 하지만, 교통 상황을 고려하지 않고 최단 경로를 검색하는 경우에는 극심한 교통 정체를 경험할 수 있다. 상근이는 오직 자기 자신만 사용 가능한 네비게이션을 만들고 있다. 이 네비게이션은 절대로 최단 경로를 찾아주지 않는다. 항상 거의 최단 경로를 찾아준다. 거의 최단 경로란 최단 경로에 포함되지 않는 도로로만

www.acmicpc.net

1. 주의할 점

- 다익스트라지만 구조체의 종류가 2개라서 헷갈릴 수 있다(make_pair를 쓰지 않을 경우)

- 다익스트라는 1번 이상 실행해야한다(최단 경로가 존재하지 않는 경우만 1번)

- 전역변수로 사용한다면 다익스트라를 실행할 때 마다 초기화를 항상 해줘야한다(가장 처음 입력받는 도로의 정보는 하지 않는다)

- 최단경로를 Memo[] 벡터에 저장해놓는다

 

2. 구현

- 다익스트라를 이용해서 최단 경로를 구하며, 해당 경로는 Memo[] 벡터에 저장해놓는다

- Memo[]에 저장된 최단경로를 DFS가 아닌 BFS를 통해 간선의 Used값을 1로 바꾼다 -> DFS로 할 경우, TLE 발생

- 거의 최단 경로 혹은 경로가 존재하지 않으면 -1을 출력한다

 

#define MAX 987654321
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
struct info {
	int idx, val;
	bool used;
};
struct info2 {
	int from, idx;
};
info tmp;
info2 tmp2;
struct cmp {
	bool operator()(info &a, info &b) {
		return a.val > b.val;
	}
};
long long dist[500];
vector<info> v[500];
vector<info2> memo[500];		//최단거리 간선번호 저장
int node, edge, start, s, e, target;
bool visit[500];

void dijkstra(bool second) {
	priority_queue<info, vector<info>, cmp> pq;
	tmp.idx = start;
	tmp.val = 0;
	pq.push(tmp);
	dist[start] = 0;
	while (!pq.empty()) {
		int cidx = pq.top().idx;
		int cv = pq.top().val;
		pq.pop();
		if (cv > dist[cidx]) continue;
		if (cidx == target && second)
			break;
		for (int i = 0; i < v[cidx].size(); i++) {
			if (!v[cidx][i].used) {
				int next = v[cidx][i].idx;
				int nv = v[cidx][i].val;
				if (dist[next] > cv + nv) {		//새로운 최단거리가 갱신될 경우
					dist[next] = cv + nv;
					tmp.idx = next;
					tmp.val = cv + nv;
					pq.push(tmp);

					//기존에 있던 경로 초기화
					memo[next].clear();
					tmp2.from = cidx;
					tmp2.idx = i;
					memo[next].push_back(tmp2);
				}
				else if (dist[next] == cv + nv) {		//같은 거리의 경로일 경우 추가
					tmp2.from = cidx;
					tmp2.idx = i;
					memo[next].push_back(tmp2);
				}
			}
		}
	}
}

void make_disable(int num) {
	queue<int> q;
	for (int i = 0; i < node; i++)
		visit[i] = false;
	visit[num] = true;
	q.push(num);
	while (!q.empty()) {
		int cidx = q.front();
		q.pop();
		if (cidx == start) continue;
		for (int i = 0; i < memo[cidx].size(); i++) {
			int from = memo[cidx][i].from;
			int idx = memo[cidx][i].idx;
			v[from][idx].used = true;
			if (!visit[from]) {
				visit[from] = true;
				q.push(from);
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
	int val;
	while (1) {
		cin >> node >> edge;
		if (node + edge == 0) break;
		cin >> start >> target;
		//초기화
		for (int i = 0; i < node; i++) {
			v[i].clear();
			dist[i] = MAX;
			memo[i].clear();
		}

		for (int i = 0; i < edge; i++) {
			cin >> s >> e >> val;
			tmp.idx = e;
			tmp.val = val;
			tmp.used = false;
			v[s].push_back(tmp);
		}
		dijkstra(false);
		if (dist[target] == MAX) {		//target까지의 거리가 존재하지 않을 경우
			cout << -1 << '\n';
			continue;
		}
		make_disable(target);
		int minDist = dist[target], result = -1;

		for (int i = 0; i < node; i++) {
			dist[i] = MAX;
			memo[i].clear();
		}
		dijkstra(true);
		if (dist[target] != minDist) 		//최단경로가 아닌 경우(거의 최단 or 없는 경로)
			result = dist[target];		
		
		if (result == MAX) 	cout << -1 << '\n';
		else cout << result << '\n';
	}
	return 0;
}
728x90
반응형

'알고리즘 > 백준' 카테고리의 다른 글

[백준 2343] 기타 레슨 (C++)  (0) 2020.03.09
[백준 2140] 지뢰찾기 (C++)  (0) 2020.03.09
[백준 1753] 최단경로 (C++)  (0) 2020.03.08
[백준 14238] 출근 기록 (C++)  (0) 2020.03.08
[백준 17073] 나무 위의 빗물 (C++)  (0) 2020.03.07
Comments