스패닝 트리(Spanning Tree)는 그래프의 모든 정점을 연결하되, 사이클이 없이 간선의 수를 최소화한 트리입니다.
📌 스패닝 트리는 여러 개가 존재할 수 있습니다.
최소 스패닝 트리(MST)는 말 그대로 가중치 합이 가장 작은 스패닝 트리입니다.
💡 예시 이미지:
📎 첫 번째 이미지:
Kruskal 알고리즘은 MST를 만들기 위한 대표적인 알고리즘 중 하나입니다.
MST 생성 시 사이클 여부 판단을 위해 사용됩니다.
class DisjointSet {
public:
DisjointSet(int n) : _parent(n), _rank(n, 1) {
for (int i = 0; i < n; i++)
_parent[i] = i;
}
int Find(int u) {
if (u == _parent[u]) return u;
return _parent[u] = Find(_parent[u]); // 경로 압축
}
void Merge(int u, int v) {
u = Find(u); v = Find(v);
if (u == v) return;
if (_rank[u] > _rank[v]) swap(u, v);
_parent[u] = v;
if (_rank[u] == _rank[v]) _rank[v]++;
}
private:
vector<int> _parent;
vector<int> _rank;
};
vector<Vertex> vertices;
vector<vector<int>> adjacent;
void CreateGraph() {
vertices.resize(6);
adjacent = vector<vector<int>>(6, vector<int>(6, -1));
adjacent[0][1] = adjacent[1][0] = 15;
adjacent[0][3] = adjacent[3][0] = 35;
adjacent[1][2] = adjacent[2][1] = 5;
adjacent[1][3] = adjacent[3][1] = 10;
adjacent[3][4] = adjacent[4][3] = 5;
adjacent[3][5] = adjacent[5][3] = 10;
adjacent[5][4] = adjacent[4][5] = 5;
}
struct CostEdge {
int cost;
int u, v;
bool operator<(CostEdge& other) {
return cost < other.cost; // 가중치 기준 오름차순
}
};
int Kruskal(vector<CostEdge>& selected) {
int totalCost = 0;
selected.clear();
vector<CostEdge> edges;
// 간선 수집
for (int u = 0; u < adjacent.size(); u++) {
for (int v = 0; v < adjacent[u].size(); v++) {
if (u > v || adjacent[u][v] == -1) continue;
edges.push_back({adjacent[u][v], u, v});
}
}
sort(edges.begin(), edges.end());
DisjointSet sets(vertices.size());
for (CostEdge& edge : edges) {
if (sets.Find(edge.u) == sets.Find(edge.v)) continue;
sets.Merge(edge.u, edge.v);
selected.push_back(edge);
totalCost += edge.cost;
}
return totalCost;
}
int main() {
CreateGraph();
vector<CostEdge> selected;
int totalCost = Kruskal(selected);
cout << "MST 총 비용: " << totalCost << endl;
return 0;
}