문제 풀이

BOJ 5214 - 환승 [C++]

khj20006 2025. 12. 6. 20:41
반응형

 

문제

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

$N$개의 역과 $M$개의 하이퍼튜브가 존재하며, 하이퍼튜브 하나는 역 $K$개를 서로 연결한다.
$1$번 역에서 $N$번 역으로 가는데 방문하는 최소 역의 수를 구해보자.

풀이

하나의 하이퍼튜브가 연결하는 $K$개의 역을 서로 모두 이어주게 된다면, 간선이 $\dfrac{K(K-1)}{2}$개 생기게 된다.

아래는 2, 4, 5, 7, 8, 9번 역을 연결하는 하이퍼튜브를 그래프에 추가시킨 그림이다.

이 방식대로 그래프를 구성한다면 전체 간선은 $O(MK^2)$만큼 생기게 되고, 이는 메모리나 시간의 제약으로 인해 불가능한 풀이가 된다.


하이퍼튜브 하나를 그래프의 새로운 가상의 정점으로 본다면 어떨까?

하나의 하이퍼튜브로 인해 추가되는 간선은 $K$개 뿐이다. 따라서 전체 간선의 개수는 $MK$개로, 최대 $1\,000\,000$개만 추가되는 것을 알 수 있다.


$i$번째 하이퍼튜브를 그래프에서 $N+i$번 정점으로 대응시킨다면 전체 정점은 $N+M$개, 간선은 $MK$개인 그래프를 구성할 수 있다.

만들어진 그래프에서 BFS로 최단 거리를 구하면 될 것같이 생겼다.

그러나 하이퍼튜브를 나타내는 가상의 정점을 지날 때 비용이 발생해서는 안 된다.

 

현재 점에서 다른 역을 방문할 때는 비용이 $1$ 발생한다고 볼 수 있지만, 하이퍼튜브를 방문할 때는 비용이 발생하지 않는다.

가중치가 두 종류$(0,1)$ 뿐인 그래프 상에서 최단 경로를 구하는 문제로 바뀐 셈이다.

따라서 0-1 BFS로 해결할 수 있다.

코드

#include <bits/stdc++.h>
using namespace std;

const int INF = 1e9 + 7;

int N, K, M;
vector<vector<int>> v(101001);

int bfs01(int start, int end) {
	vector<int> dist(101001, INF);
	deque<pair<int, int>> q;
	dist[start] = 1;
	q.emplace_back(1, start);
	while (!q.empty()) {
		auto [d, n] = q.front(); q.pop_front();
		for (int i : v[n]) {
			int cost = i > N ? 0 : 1;
			if (dist[i] > d + cost) {
				dist[i] = d + cost;
				if (cost) q.emplace_back(dist[i], i);
				else q.emplace_front(dist[i], i);
			}
		}
	}
	return dist[end] == INF ? -1 : dist[end];
}

int main() {
	cin.tie(0)->sync_with_stdio(0);

	cin >> N >> K >> M;
	for (int i = 1; i <= M; i++) {
		for (int j = 1, a; j <= K; j++) {
			cin >> a;
			v[a].push_back(N + i);
			v[N + i].push_back(a);
		}
	}

	cout << bfs01(1, N);

}
반응형

'문제 풀이' 카테고리의 다른 글

LeetCode 3043. Find the Length of the Longest Common Prefix  (0) 2026.05.22
LeetCode 4. Median of Two Sorted Arrays  (0) 2026.05.19
BOJ 9376 - 탈옥 [C++]  (0) 2025.12.04
BOJ 9328 - 열쇠 [Java]  (0) 2025.01.23
BOJ 2806 - DNA 발견 [Java]  (0) 2025.01.23