[ 백준 ] 15971 / 두 로봇

金弘均·2021년 9월 16일
0

Baekjoon Online Judge

목록 보기
222/228
post-thumbnail
post-custom-banner

# Appreciation

/*
 * Problem :: 두 로봇 / 15971
 *
 * Kind :: BFS
 *
 * Insight
 * - 임의의 두 방 사이를 이동할 때 같은 통로를 두 번 이상 지나지 않는 경로는 유일한 것으로 밝혀졌다
 *   + 한 로봇이 있는 지점을 시작점으로, 다른 로봇이 있는 지점까지를 도착점으로 한
 *     BFS 나 DFS 돌려서 동굴을 통해 이동한 총 이동거리를 구해주자
 *     # 근데 두 로봇이 같은 통로에 위치해있으면 통신이 가능하다
 *       이는 이동한 동굴들 중 한 동굴은 굳이 통신을 위해 이동하지 않아도 된다는 뜻이다
 *       두 로봇이 그 동굴의 맞은편에 있으면 통신이 가능하기 때문이다
 *       -> 통신하기 위해 이동해야 하는 총 거리의 최솟값을 구하는 것이므로
 *          이동하지 않을 동굴은 한 로봇이 다른 로봇이 있는 지점까지 갈 때
 *          거쳐간 동굴들 중 가장 긴 동굴이다
 *          => 이동한 동굴들 중 가장 긴 동굴의 길이를 총 이동거리에서 빼주자
 *
 * Point
 * - BFS 로 풀까 DFS 로 풀까...
 *   + 처음 문제를 풀 때는 DFS 로 풀었지만...
 *     도착점을 방문했을 때 더이상 DFS 를 진행하지 않고 끝내야 하는 것에 좀 애를 먹었다
 *     # 전역변수로 가장 긴 동굴의 길이와 총 이동길이를 구할 수 있지만
 *       뭔가 더 깔끔하고 멋있게 이를 함수안에서 모두 처리할려 했더니
 *       return 해주어야 하는 값으로 '발견했다' 라는 뜻의 bool 변수와
 *       '이동해야하는 최소거리' 라는 int 변수로 총 2개였다
 *       -> Python 이라면 상관없을텐데...
 *          C++ 은 이 경우 코드가 조금 복잡해진다
 *          그래서 DFS 는 별로인것 같다
 *   + 실제로 BFS 는 중간상태로
 *     {현재 방의 번호, 총 이동거리, 가장 긴 동굴의 길이} 정보만 계속 추적해주고
 *     평범한 BFS 를 돌리면 되니 훨씬 직관적이고 편하다
 */

# Code

//
//  BOJ
//  ver.C++
//
//  Created by GGlifer
//
//  Open Source

#include <iostream>
#include <queue>
#include <cstring>

using namespace std;

#define endl '\n'

// Set up : Global Variables
struct Node { int no, dist; };
struct Status { int no, allDist, maxDist; };

// Set up : Functions Declaration
/* None */


int main()
{
    // Set up : I/O
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // Set up : Input
    int N, s, e;
    cin >> N >> s >> e;
    /* L[i] = {i 번 방과 연결되는 다른 방 그 다른 방과 연결된 동굴의 길이}
     *        정보들을 저장한 Vector */
    vector<Node> L[N+1];
    for (int i=0; i<N-1; i++) {
        int no1, no2, dist;
        cin >> no1 >> no2 >> dist;
        L[no1].push_back({no2, dist});
        L[no2].push_back({no1, dist});
    }

    // Process
    queue<Status> que;
    bool isVisited[N+1];
    memset(isVisited, false, sizeof(isVisited));

    /* Status.no = 현재 방 번호
     * Status.allDist = 시작점부터 현재 방까지 이동한 거리
     * Status.maxDist = 시작점부터 현재 방까지 거쳐온 동굴 중 가장 긴 동굴의 길이 */
    que.push({s, 0, 0});
    isVisited[s] = true;

    /* BFS */
    while (not(que.empty())) {
        int c = que.front().no;
        int ad = que.front().allDist;
        int md = que.front().maxDist;
        que.pop();

        // Control : Output
        if (c == e) {
            cout << ad - md << endl;
            exit(0);
        }

        for (Node node : L[c]) {
            int n = node.no;
            int d = node.dist;
            if (not(isVisited[n])) {
                isVisited[n] = true;
                que.push({n, ad+d, max(md,d)});
            }
        }
    }
}

// Helper Functions
/* None */
profile
이런 미친 게임을 봤나! - 옥냥이
post-custom-banner

0개의 댓글