Make Unreal REAL.
article thumbnail
1197. 최소 스패닝 트리

 

 

최소 신장 트리(MST)를 구하는 기본적인 문제이다.

  • MST는 머리, 손, 발, 몸통이 따로 있다고 할 때, 말 그대로 키(신장)가 가장 작도록 모든 노드를 연결하는 트리다.
  • N개의 노드가 있을 때, MST의 간선 개수는 항상 N - 1이 된다.
  • 유니온-파인드를 필수적으로 활용해 크루스칼 알고리즘을 이용한다.

 

  1. 가중치의 오름차순으로 정렬된 간선 리스트를 만든다.
  2. 연결된 간선 개수가 N - 1이 될때까지 반복한다.
  3. 간선 리스트에서 간선을 하나씩 꺼내, 대표 노드가 같지 않을 때(싸이클이 생기지 않을 때)만 union으로 대표 노드끼리 연결한다.

 

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <numeric>

using namespace std;

int findRep(vector<int>& rep, int i)
{
    if (rep[i] == i)
        return i;
    
    return rep[i] = findRep(rep, rep[i]);
}

bool unionAB(vector<int>& rep, int a, int b)
{
    int repA = findRep(rep, a);
    int repB = findRep(rep, b);

    if (repA == repB)
        return false;

    rep[repA] = rep[repB] = min(repA, repB);

    return true;
}

struct Edge
{
    int s;
    int e;
    int w;

    friend bool operator < (const Edge& A, const Edge& B) { return A.w > B.w; }
};

int main(int argc, char* argv[])
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    int V, E;
    cin >> V >> E;

    priority_queue<Edge> edges;

    while (E--)
    {
        int s, e, w;
        cin >> s >> e >> w;

        edges.push({s, e, w});
    }

    int nConnected = 0, answer = 0;
    vector<int> rep(V + 1);

    iota(rep.begin(), rep.end(), 0);

    while (nConnected < V - 1)
    {
        Edge edge = edges.top(); edges.pop();

        if (unionAB(rep, edge.s, edge.e))
        {
            answer += edge.w;
            ++nConnected;
        }
    }

    cout << answer;

    return 0;
}

 

우선순위 큐보다는 벡터에 담은 후 정렬하는 것이 더 빠르다.

 

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>

using namespace std;

int findRep(vector<int>& rep, int i)
{
    if (rep[i] == i)
        return i;
    
    return rep[i] = findRep(rep, rep[i]);
}

bool unionAB(vector<int>& rep, int a, int b)
{
    int repA = findRep(rep, a);
    int repB = findRep(rep, b);

    if (repA == repB)
        return false;

    rep[repA] = rep[repB] = min(repA, repB);

    return true;
}

struct Edge
{
    int s;
    int e;
    int w;

    friend bool operator < (const Edge& A, const Edge& B) { return A.w < B.w; }
};

int main(int argc, char* argv[])
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    int V, E;
    cin >> V >> E;

    vector<Edge> edges;

    while (E--)
    {
        int s, e, w;
        cin >> s >> e >> w;

        edges.push_back({s, e, w});
    }

    sort(edges.begin(), edges.end());

    int nConnected = 0, answer = 0;
    vector<int> rep(V + 1);

    iota(rep.begin(), rep.end(), 0);

    for (Edge& edge : edges)
    {
        if (unionAB(rep, edge.s, edge.e))
        {
            answer += edge.w;

            if (V - 1 <= ++nConnected)
                break;
        }
    }

    cout << answer;

    return 0;
}

'자료구조 & 알고리즘 > 백준' 카테고리의 다른 글

11441. 합 구하기  (0) 2023.09.14
11657. 타임머신  (0) 2023.09.13
1865. 웜홀  (0) 2023.09.09
11003. 최솟값 찾기  (0) 2023.09.08
5597. 과제 안 내신 분..?  (0) 2023.02.28
profile

Make Unreal REAL.

@diesuki4

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그