danbibibi
article thumbnail

문제

문제 바로가기> BOJ 16947번: 서울 지하철 2호선

 

16947번: 서울 지하철 2호선

첫째 줄에 역의 개수 N(3 ≤ N ≤ 3,000)이 주어진다. 둘째 줄부터 N개의 줄에는 역과 역을 연결하는 구간의 정보가 주어진다. 같은 구간이 여러 번 주어지는 경우는 없고, 역은 1번부터 N번까지 번호

www.acmicpc.net

 

풀이

1. dfs를 이용해 cycle을 구해준다. 

    이전 노드가 아닌, 다른 노드에서 방문한 노드를 재방문 하는 경우, cycle이라고 볼 수 있다!

2. bfs를 이용해 역과 순환선 사이의 거리를 구해준다!

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#define MAX 3005
using namespace std;

struct QUEUE{ int n, d; };

int N;
bool isFind; // cycle을 찾았는지
int pre[MAX]; // 이전 역
int dist[MAX]; // 순환선과의 거리
bool cycle[MAX]; // 순환선 여부
bool visited[MAX];
vector<int> station[MAX];

void input(){
    cin >> N;
    for (int i = 0; i < N; i++){
        int a, b;
        cin >> a >> b;
        station[a].push_back(b);
        station[b].push_back(a); // 양방향
    }
}

void find_cycle(int cur){
    visited[cur] = true;
    for(int nxt : station[cur]){
        if(isFind) return;
        if(visited[nxt]){
            if(nxt != pre[cur]){ // cycle을 찾은 경우
                isFind = true;
                cycle[cur] = true;

                int tmp = cur;
                while (tmp != nxt){ // cycle 역 추적
                    cycle[pre[tmp]] = true;
                    tmp = pre[tmp];
                }
            }
        }
        else{
            pre[nxt] = cur;
            find_cycle(nxt);
        }
    }
}

void get_dist(){

    // 1. 초기화
    memset(visited, false, sizeof(visited));

    // 2. 시작점 처리
    queue<QUEUE> q;
    for (int n = 1; n <= N; n++){
        if(cycle[n]) {
            visited[n] = true;
            q.push((QUEUE){n, 0});
        }
    }

    // 3. bfs
    while (!q.empty()){
        int n = q.front().n;
        int d = q.front().d;
        q.pop();

        for(int nxt : station[n]){
            if(visited[nxt]) continue;
            visited[nxt] = true;
            q.push((QUEUE){nxt, d + 1});
            dist[nxt] = d + 1;
        }
    }
}

void output(){
    for (int n = 1; n <= N; n++)
        cout << dist[n] << " ";
}

void solve(){
    
    // 1. 순환 노선 찾기
    find_cycle(1);

    // 2. n번 역과 순환선 사이 거리 구하기
    get_dist();

    // 3. n번 역과 순환선 사이 거리 출력
    output();
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    // freopen("../test/input.txt", "r", stdin);
    input();
    solve();
}

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

BOJ 20040번: 사이클 게임  (1) 2024.03.24
BOJ 3020번: 개똥벌레  (0) 2024.03.20
BOJ 5719번: 거의 최단 경로  (0) 2024.02.21
BOJ 12851번: 숨바꼭질 2  (0) 2024.02.21
BOJ 1938번: 통나무 옮기기  (1) 2024.02.18
profile

danbibibi

@danbibibi

꿈을 꾸는 시간은 멈춰 있는 것이 아냐 두려워하지 마 멈추지 마 푸른 꿈속으로