10-5. [C/C++] MST를 위한 Prim 알고리즘

2023. 8. 16. 23:53·Computer Science/Data Structure

Prim 알고리즘

Prim 알고리즘은 하나의 정점에서부터 시작해 트리를 단계적으로 확장해나가는 방법이다.

 

처음에는 시작 정점만이 MST에 포함된다.

다음으로 지금까지 만들어진 MST에 인접한 정점들 중에서 간선의 가중치가 가장 작은 정점을 선택하여 트리를 확장한다.

이 과정을 트리가 (n - 1)개의 간선을 가질 때까지 계속한다.

Prim()

(1) 그래프에서 시작 정점을 선택해 초기 MST를 만든다.
(2) 현재 MST의 정점들과 인접한 정점들 중에서 간선의 가중치가 가장 작은 정점 v를 선택한다.
(3) 이 정점 v와 이때의 간선을 MST에 추가한다.
(4) 모든 정점이 삽입될 때 까지 2번으로 이동한다.

Kruskal 알고리즘이 간선을 중심으로 하는 알고리즘인데 비해 Prim 알고리즘은 정점을 중심으로 한다.


Prim 알고리즘의 구현

Prim 알고리즘 자체는 크게 복잡하지는 않지만 구현하기 위해 고려해야 할 것들이 있다.

 

첫 번째는 현재 MST에 인접한 정점들 중에서 가장 비용이 적게 드는 간선을 찾는 과정이다.

이것을 위해 우선 순위 큐를 사용할 것이다.

가중치는 기준으로 우선 순위 큐(최소 힙)를 사용하면 큐에서 가중치가 가장 작은 간선을 선택해 줄 것이다.

 

두 번째는 MST가 사이클을 형성하게 되는 것을 막아야 하는 것이다.

Prim 알고리즘은 간선을 중심으로 하는 Kruskal 알고리즘과 달리 정점을 중심으로 한다.

그렇기 때문에 집합이 형성되는 지 확인하는 것이 아니고, 정점이 이미 MST에 포함되어 있는지 검사한다.

이를 위해 bool visited[] 배열을 사용할 것이다.


코드로 구현

 

1197번: 최소 스패닝 트리

첫째 줄에 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)가 주어진다. 다음 E개의 줄에는 각 간선에 대한 정보를 나타내는 세 정수 A, B, C가 주어진다. 이는 A번 정점과 B번 정점이

www.acmicpc.net

이 문제를 Prim 알고리즘을 이용해 해결해 봤다.

// prim.cpp
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define SIZE 10001

int V, E;
vector<pair<int, int>> graph[SIZE];
priority_queue<pair<int, int>> pq;
bool visited[SIZE];
long long ans;

void prim() {
    pq.push({0, 1});

    while (!pq.empty()) {
        int curWeight = -pq.top().first;
        int curNode = pq.top().second;
        pq.pop();

        if (visited[curNode]) continue;

        visited[curNode] = true;
        ans += curWeight;

        for (int i = 0; i < graph[curNode].size(); i++) {
            int nextNode = graph[curNode][i].first;
            int nextWeight = graph[curNode][i].second;

            pq.push({-nextWeight, nextNode});
        }
    }
}

int main() {
    cin >> V >> E;
    for (int i = 0; i < E; i++) {
        int u, v, weight;
        cin >> u >> v >> weight;
        graph[u].push_back({v, weight});
        graph[v].push_back({u, weight});
    }

    prim();
    cout << ans << endl;

    return 0;
}

위 코드는 아래 이미지를 클릭해 깃허브에서도 확인할 수 있다.

깃허브 이미지 링크

저작자표시 (새창열림)

'Computer Science > Data Structure' 카테고리의 다른 글

11-2. [C/C++] Dijkstra의 최단 경로 알고리즘  (0) 2023.08.22
11-1. 가중치 그래프에서의 최단 경로  (0) 2023.08.22
10-4. [C/C++] MST를 위한 Kruskal 알고리즘  (0) 2023.08.16
10-3. 최소 비용 신장 트리란?  (0) 2023.08.16
10-2. [C/C++] 인접 행렬을 이용한 가중치 그래프의 구현  (0) 2023.08.16
'Computer Science/Data Structure' 카테고리의 다른 글
  • 11-2. [C/C++] Dijkstra의 최단 경로 알고리즘
  • 11-1. 가중치 그래프에서의 최단 경로
  • 10-4. [C/C++] MST를 위한 Kruskal 알고리즘
  • 10-3. 최소 비용 신장 트리란?
Study with Me!
Study with Me!
Study with Me!
  • Study with Me!
    Seongmo
    Study with Me!
  • 전체
    오늘
    어제
    • Computer (136)
      • Computer Science (61)
        • Data Structure (51)
        • Algorithm (6)
        • 선형대수 with C++ (4)
      • Arm Architecture (1)
        • Register (0)
        • Assembly Instruction (1)
      • Linux (32)
        • Linux Kernel (4)
        • 라이브러리 함수 구현하기 (0)
        • 쉘, 쉘 명령어 구현하기 (15)
        • Ubuntu (13)
      • Cloud Infrastructure (8)
        • Kubernetes (7)
        • OpenStack Magnum (1)
      • AWS (3)
      • Baekjoon (18)
      • Tools (6)
        • Git & Github (5)
        • Vim (1)
      • 개발 환경 (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    STL
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Study with Me!
10-5. [C/C++] MST를 위한 Prim 알고리즘
상단으로

티스토리툴바