알고리즘 모음(C++)

백준 1504 - 특정한 최단 경로(C++) 본문

백준

백준 1504 - 특정한 최단 경로(C++)

공대생의 잡다한 사전 2022. 3. 9. 01:17

문제 링크입니다. https://www.acmicpc.net/problem/1504

 

1504번: 특정한 최단 경로

첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존

www.acmicpc.net

다익스트라를 여러번 사용하면 되는 문제입니다.

다익스트라를 여러번 사용해야 되는 문제입니다.

다익스트라 알고리즘을 모르신다면 https://junseok.tistory.com/187 를 참고해주세요

문제에서 주어진 두 정점을 무조건 지났을 때의 최솟값을 구하는 문제입니다. 이 두점을 First, Second로 정하겠습니다.

 

1번 정점에서 시작해 First와 Second를 지나고 N점까지 도착할 수 있는 길은 2가지입니다.

1. 1번 정점 -> First -> Second -> N

2. 2번 정점 -> Second -> First -> N

이 두 방법중 하나 이상이 가능할 때, 최솟값을 비교한 뒤, 출력해주면 됩니다.

두 방법 전부 불가능할 때, -1를 출력해주면 됩니다.

 

그렇다면 먼저 구해야할 것은 

"1 -> First로 갈 수 있냐" , "1 - > Second로 갈 수 있냐" 를 확인해야합니다.

 

그 다음으로는 "First -> Second로 갈 때의 값"을 구해야합니다. "Second -> First로 갈 때의 값"을 구하지 않아도 되는 이유는 간선이 양방향이기에, 둘 중 한개의 값만 구하면 다른 값도 같은 값으로 나오기 때문입니다.

 

마지막으로는 "First -> N으로 갈 때의 값" , "Second -> N으로 갈 때의 값" 을 각각 구해주면 됩니다.

구한 값을 각각의 루트 값에 더해주면 됩니다.

 

 

1. 1 -> First로 갈 수 있냐 , 1 - > Second로 갈 수 있냐

	Dijkstra(1);
	ans_A = Distance[First];
	ans_B = Distance[Second];
	if (ans_A == INF) go_A = false;
	if (ans_B == INF) go_B = false;

다익스트라를 1번 점에서 시작합니다.

1번 점에서 시작했을 때, First or Second에 도착하지 못했다면 N번 점까지 도달하지 못한다는 의미임으로 false로 바꿔줬습니다.

 

 

2. First -> Second로 갈 때의 값

Dijkstra(First);
	if (go_A) ans_A += Distance[Second];
	if (go_B) ans_B += Distance[Second];

First에서 시작해서 Second로 도착한 값을 구해줍니다.

1번과 First가 연결되어 있다면(go_A 값이 true일 때) 해당 값을 더해줍니다.

1번과 Second가 연결되어 있다면(go_B 값이 true일 때) 해당 값을 더해줍니다.

 

 

3. First -> N으로 갈 때의 값 , Second -> N으로 갈 때의 값

	Dijkstra(Second);
	if (go_A) ans_A += Distance[N];
	Dijkstra(First);
	if (go_B) ans_B += Distance[N];

Second에서 시작해 N으로 가는 값을 구했다면 "1번 정점 -> First -> Second -> N" 의 경우입니다. 따라서 해당 값에 더해줍니다.

First에서 시작해 N으로 가는 값을 구했다면 "2번 정점 -> Second -> First -> N" 의 경우입니다. 따라서 해당 값에 더해줍니다.

 

 

자세한 것은 코드를 참고해주세요

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <cmath>
#define INF 210000000000

using namespace std;

priority_queue < pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> q;
long long Distance[801];
int N, M;
int First, Second;
vector<pair<int, int>> line[801];

void reset_Distance() {
	for (int i = 1; i <= N; i++) {
		Distance[i] = INF;
	}
}

void Dijkstra(int start) {
	reset_Distance();
	Distance[start] = 0;
	q.push({ 0, start });
	while (!q.empty()) {
		int x = q.top().second;
		int cost = q.top().first;
		q.pop();
		for (int i = 0; i < line[x].size(); i++) {
			int xx = line[x][i].first;
			int Cost = line[x][i].second;
			if (Distance[xx] > Distance[x] + Cost) {
				Distance[xx] = Distance[x] + Cost;
				q.push({ Distance[xx] , xx });
			}
		}
	}
}

void solve() {
	bool go_A = true, go_B = true;
	long long ans_A = 0, ans_B = 0;
	/////////////////////////////////////////////// 길찾기 시작
	Dijkstra(1);
	ans_A = Distance[First];
	ans_B = Distance[Second];
	if (ans_A == INF) go_A = false;
	if (ans_B == INF) go_B = false;
	Dijkstra(First);
	if (go_A) ans_A += Distance[Second];
	if (go_B) ans_B += Distance[Second];
	Dijkstra(Second);
	if (go_A) ans_A += Distance[N];
	Dijkstra(First);
	if (go_B) ans_B += Distance[N];
	////////////////////////////////////////////// 길찾기 완료
	if (!go_A && !go_B) cout << "-1";
	else {
		long long ans = min(ans_A, ans_B);
		if (ans == INF) cout << "-1";
		else cout << ans;
	}
}

int main()
{
	cin.tie(0);
	cout.tie(0);
	cin >> N >> M;
	for (int i = 0; i < M; i++) {
		int x, y, cost;
		cin >> x >> y >> cost;
		line[x].push_back({ y,cost });
		line[y].push_back({ x,cost });
	}
	cin >> First >> Second;
	solve();
	return 0;
}

 

 

질문 및 조언 댓글 남겨주세요

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

백준 11779 - 최소비용 구하기 2(C++)  (0) 2022.03.09
백준 1238 - 파티(C++)  (0) 2022.03.09
백준 1916 - 최소비용 구하기(C++)  (0) 2022.03.07
백준 1753 - 최단경로(C++)  (0) 2022.03.07
백준 1865 - 웜홀(C++)  (0) 2022.03.06