MST 관련 설명은 이전 페이지인 Prim 알고리즘 페이지에 있습니다.
해당 알고리즘을 코드로 구현하려면 Union-Find 알고리즘을 알아야합니다.
전체 간선을 탐색하면서 MST를 찾는 알고리즘
사이클을 확인할때 union-find 알고리즘을 사용합니다.
class Infor {
public:
int w;
int s;
int f;
Infor() { w = 0; s = 0; f = 0; }
Infor(int w, int s, int f) {
this->w = w;
this->s = s;
this->f = f;
}
};
bool compare(Infor a, Infor b) { return a.w < b.w; }
int Find(int x) {
if (x == parent[x]) return x;
else return parent[x] = Find(parent[x]);
}
int kruscal(){
vector<int> parent;
// union-find 를 위한 배열
// 부모노드의 번호를 가리킴
vector<Infor> kruscal;
// 가중치, 시작지점, 도착지점이 저장되어 있다
parent.resize(v + 1);
for (int i = 1; i <= v; i++) {
parent[i] = i;
}
// 자기자신을 가리킴 -> 자기자신이 루트노드
int s, f, w;
for (int i = 0; i < e; i++) {
cin >> s >> f >> w;
kruscal.push_back({ w,s,f });
}
sort(kruscal.begin(), kruscal.end(), compare);
// 모든 간선을 가중치 기준 오름차순으로 정렬
int result = 0;
int cnt = 0;
int rs, rf;
for (auto& cur : kruscal) {
rs = Find(cur.s);
rf = Find(cur.f);
if (rs == rf) continue;
// 루트노드가 같다 -> 해당 간선을 추가하면 사이클 생성됨
result += cur.w;
// MST를 구하는데 필요한 가중치를 모두 더한다
// 다른 로직으로 변경가능
if (rs > rf) parent[rs] = rf;
else parent[rf] = rs;
// 두 노드가 속한 트리를 합치는 과정
cnt++;
if (cnt == v - 1) break;
// 모든 정점의 개수 - 1 번 반복했다면 최적화를 위해 종료한다.
}
return result;
}
시간복잡도:
모든 간선을 정렬하는데 걸리는 시간:
간선하나씩 탐색하면서 MST만드는 시간: