Prim's algorithm
프림알고리즘은 최소신장트리, MST(minimum spanning tree)를 찾는 알고리즘이다.
최소신장트리 는 무향그래프의 모든 정점을 잇는 신장트리 중 그 가중치의 합이 최소인 그래프이다.
알고리즘은 다음과 같다.
- (1) 시작할 정점을 선택한다. 아무 정점이나 선택해도 된다.
- (2) 선택한 정점에서 갈 수 있는 다른 정점 중 가장 가중치가 작은 정점을 선택해 잇는다.
- (3) 이어진 정점들에서 갈 수 있는 정점 중 가장 가중치가 작은 정점을 선택해 잇는다.
- (4) 모든 정점을 선택할 때 까지 (3)과정을 계속 반복
이어진 정점이라고 표기했는데 선택한 정점이 최소신장트리에 포함되는 것이며,
지금까지 선택한 모든 정점들에서 선택하지 않은 정점까지의 가중치가 가장 작은 것 을 선택하는 것이다.
작은 것들만 선택하는 것에서 알 수 있듯 그리디 알고리즘이다.
구현은 다익스트라의 구현과 마찬가지로 우선순위큐를 사용할 것이다.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
priority_queue<pair<ll, int>> PQ;
vector<pair<int, ll>> vertex[10001];
//vertex[i] : 정점i에서 갈 수 있는 다른 정점과 가중치를 원소로 가짐
bool vist[10001];
int main()
{
ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
int V, E, A, B;
ll C, ans = 0;
cin >> V >> E;
for (int i = 0; i < E; i++)
{
cin >> A >> B >> C;
vertex[A].push_back(make_pair(B, C));
vertex[B].push_back(make_pair(A, C));
}
//아무데서나 시작!
PQ.push(make_pair(0, 1));
while (!PQ.empty())
{
int Ver = PQ.top().second;
int Cost = -PQ.top().first;
PQ.pop();
if (vist[Ver]) continue;//MST에 추가돼있는거면 패스
vist[Ver] = true; //선택한 정점은 방문처리를 해줌
ans += Cost; //가중치 더해줌
for (int i = 0; i < vertex[Ver].size(); i++)
{
//연결된 정점들 중 MST에 추가돼있는거면 패스
if (vist[vertex[Ver][i].first]) continue;
//Ver에서 갈 수 있는 다른 정점과 그 가중치를 큐에 추가
PQ.push(make_pair(-vertex[Ver][i].second, vertex[Ver][i].first));
}
}
return 0;
}