문제
풀이
- 크루스칼 알고리즘을 이용하였다.
- 가중치가 작은 순서대로 검사할 수 있도록 간선을 가중치의 오름차순으로 정렬한다.
- 검사하는 간선이 사이클을 만들지 않다면 간선을 선택한다.
- 간선이 선택되면 선택된 간선의 노드를 같은 부모로 설정한다.
- 모든 간선을 검사하거나, 간선이 (총 노드의 수 - 1)만큼 선택되었다면 종료된다.
코드
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct
{
int v1;
int v2;
int dist;
}edge;
int parent[10001];
bool compare(const edge edge1, const edge edge2)
{
return edge1.dist < edge2.dist;
}
// v의 최상위 부모 노드를 반환
int getParent(int v)
{
if (parent[v] == v)
{
return v;
}
return getParent(parent[v]);
}
// 현재 사이클이 생기는지(부모 노드가 같은지) 확인
bool Cycle(int v1, int v2)
{
v1 = getParent(v1);
v2 = getParent(v2);
return v1 == v2;
}
// v1과 v2의 부모 노드를 같게 설정
void Union(int v1, int v2)
{
int p1 = getParent(v1);
int p2 = getParent(v2);
if (p1 < p2)
{
parent[p2] = p1;
}
else
{
parent[p1] = p2;
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(nullptr);
int V, E;
vector<edge> edges;
long long answer = 0;
cin >> V >> E;
for (int i = 0; i < E; ++i)
{
int A, B, C;
cin >> A >> B >> C;
edges.push_back({ A, B, C });
}
// 가중치가 작은 순으로 정렬
sort(edges.begin(), edges.end(), compare);
// 초기 부모는 자신으로 설정
for (int i = 1; i <= V; ++i)
{
parent[i] = i;
}
for (edge e : edges)
{
// 사이클이 생기지 않는다면 간선을 선택하고 Union
if (!Cycle(e.v1, e.v2))
{
answer += e.dist;
Union(e.v1, e.v2);
}
}
cout << answer;
return 0;
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준][C++] 1806: 부분합 (0) | 2023.10.11 |
---|---|
[백준][C++] 1647: 도시 분할 계획 (2) | 2023.10.10 |
[백준][C++] 27172: 수 나누기 게임 (1) | 2023.10.08 |
[백준][C++] 2467: 용액 (1) | 2023.10.07 |
[백준][C++] 2166: 다각형의 면적 (0) | 2023.10.06 |