https://www.acmicpc.net/problem/18232
18232번: 텔레포트 정거장
첫 번째 줄에 정수 N, M이 공백으로 구분되어 주어진다. (2 ≤ N ≤ 300,000, 0 ≤ M ≤ min(N×(N-1)/2, 300,000)) 두 번째 줄에 정수 S, E가 공백으로 구분되어 주어진다. (1 ≤ S, E ≤ N, S ≠ E) 그 다음 줄부터 M
www.acmicpc.net
각 점을 노드로, 텔레포트 혹은 이웃한 점으로 이동하는 것을 에지로 본다면 이 문제는 bfs를 이용해 그래프를 탐색하는 문제로 볼 수 있다.
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define MAX_N 300000
// visit[n]: 노드 n에 방문했다면 true, 아니면 false
bool visit[MAX_N + 1];
// N: 노드의 수
int N;
// q: bfs를 위한 큐
queue<int> q;
// 큐에 n을 push
void push(int n) {
// 노드 n이 valid한 노드이고 아직 방문한 적 없다면 q에 push한 다음 방문함을 표시
if (n >= 1 && n <= N && !visit[n]) {
q.push(n);
visit[n] = true;
}
}
int main() {
// 입출력 속도 향상
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// M: 텔레포트의 수, S: 시작 노드/현재 노드, E: 목표 노드, a, b: 입력을 위한 버퍼
// len: 이중 for문을 회피하기 위해 만든 q의 초기 길이 변수
// time: 시작 노드에서 현재 노드까지 이동하기 위해 걸리는 시간
int M, S, E, a, b, len = 1, time = 0;
// v[i]: 노드 i에서 텔레포트로 갈 수 있는 노드의 집합
vector<int> v[MAX_N + 1];
// 문제 조건 입력
cin >> N >> M >> S >> E;
while (M--) {
cin >> a >> b;
// 텔레포트는 양방향이므로 v에도 양방향으로 push
v[a].push_back(b);
v[b].push_back(a);
}
// q에 시작 노드 S를 push
push(S);
// 방문 가능한 모든 노드에 대해
while (!q.empty() && !visit[E]) {
// 이전 스텝의 노드를 모두 방문했다면
if (!--len) {
// q의 알려진 길이를 갱신하고 시간을 1 늘린다
len = q.size();
time++;
}
// q에서 노드 하나를 꺼내와 S에 저장
S = q.front();
q.pop();
// 인접한 노드와 텔레포트 가능한 노드를 q에 push
push(S - 1); push(S + 1);
for (auto i: v[S]) push(i);
}
// S -> E에 걸린 시간을 출력
cout << time << '\n';
return 0;
}
'알고리즘 > 문제 풀이' 카테고리의 다른 글
백준 18870번: 좌표 압축 (0) | 2022.01.14 |
---|---|
백준 18248번: 제야의 종 (0) | 2022.01.14 |
백준 18119번: 단어 암기 (0) | 2022.01.14 |
백준 18111번: 마인크래프트 (0) | 2022.01.14 |
백준 18108번: 1998년생인 내가 태국에서는 2541년생?! (0) | 2022.01.14 |