[ 백준 ] 1647 / 도시 분할 계획

金弘均·2021년 9월 14일
0

Baekjoon Online Judge

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

# Appreciation

/*
 * Problem :: 1647 / 도시 분할 계획
 * 
 * Kind :: MST
 *
 * Insight
 * - 하나의 마을에서 길의 유지비의 합을 최소로 -> 최소 스패닝 트리
 *   + 두 마을로 나누어 길의 유지비 합을 최소로 -> 최소 스패닝 트리인데...
 *     만들어진 최소 스패닝 트리에서 길의 유지비가 가장 많이 드는 길을 없애면
 *     자연스레 두 마을로 분리가 된다!
 *     -> N 개의 노드로 이루어진 그래프에서,
 *        유니온-파인드 알고리즘과 우선순위 큐를 이용
 *        최소 스패닝 트리를 만들 때 N-1 개의 엣지를 더했는데
 *        그 중 가중치가 가장 큰 엣지를 하나 없애야 한다면
 *        처음부터 N-2 개의 엣지만 더해주자
 */

# Code

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

#include <iostream>
#include <queue>
#include <tuple>

using namespace std;

#define endl '\n'

// Set up : Global Variables
#define MAX 100000
int P[MAX+1], R[MAX+1];
struct Road { int a, b, c; };

// Set up : Functions Declaration
bool operator < (Road u, Road v);
void merge(int x, int y);
int find(int x);


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

    // Set up : Input
    int N, M;
    cin >> N >> M;
    priority_queue<Road> PQ;
    for (int i=0; i<M; i++) {
        int A, B, C;
        cin >> A >> B >> C;
        PQ.push({A, B, C});
    }

    // Process
    for (int i=1; i<=N; i++) {
        P[i] = i;
        R[i] = 1;
    }

    int cnt = 0, ans = 0;
    while (cnt < N-2) { /* N-2 개의 길만 연결하면 자연스레 두 마을로 분리가 됨 */
        auto [a, b, c] = PQ.top();
        PQ.pop();

        if (find(a) != find(b)) {
            merge(a, b);
            cnt++;
            ans += c;
        }
    }

    // Control : Output
    cout << ans << endl;
}

// Helper Functions
bool operator < (const Road u, const Road v)
/* Road 구조체 비교를 위한 연산자 오버로딩 */
{
    return make_tuple(-u.c, u.a, u.b) < make_tuple(-v.c, v.a, v.b);
}

void merge(int x, int y)
/* Union Find 알고리즘의 Union */
{
    x = find(x);
    y = find(y);

    if (R[x] < R[y]) swap(x, y);

    P[y] = x;
    if (R[x] == R[y]) R[x]++;
}

int find(int x)
/* Union Find 알고리즘의 Find */
{
    if (P[x] == x) return x;
    return P[x] = find(P[x]);
}
profile
이런 미친 게임을 봤나! - 옥냥이
post-custom-banner

0개의 댓글