1197번: 최소 스패닝 트리 (acmicpc.net)
1197번 : 최소 스패닝 트리
그래프가 주어졌을 때, 그 그래프의 최소 스패닝 트리를 구하는 프로그램을 작성하시오.
최소 스패닝 트리는, 주어진 그래프의 모든 정점들을 연결하는 부분 그래프 중에서 그 가중치의 합이 최소인 트리를 말한다.
입력
첫째 줄에 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)가 주어진다. 다음 E개의 줄에는 각 간선에 대한 정보를 나타내는 세 정수 A, B, C가 주어진다. 이는 A번 정점과 B번 정점이 가중치 C인 간선으로 연결되어 있다는 의미이다. C는 음수일 수도 있으며, 절댓값이 1,000,000을 넘지 않는다.
그래프의 정점은 1번부터 V번까지 번호가 매겨져 있고, 임의의 두 정점 사이에 경로가 있다. 최소 스패닝 트리의 가중치가 -2,147,483,648보다 크거나 같고, 2,147,483,647보다 작거나 같은 데이터만 입력으로 주어진다.
출력
첫째 줄에 최소 스패닝 트리의 가중치를 출력한다.
생각해 볼 점
최소 스패닝 트리에 관한 문제입니다.
최소 스패닝 트리를 푸는 방법에는 크게 크루스칼 알고리즘과 프림 알고리즘이 있습니다.
최소 신장 트리 (MST, 크루스칼, 프림 알고리즘) (velog.io)
알고리즘에 대해서는 위 링크를 참조합니다.
저는 크루스칼 알고리즘을 이용해 풀었습니다.
코드
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//에지 (A -> B & Cost)
struct ABC
{
int A;
int B;
int C;
};
//비교함수
bool cmp(ABC ele1, ABC ele2)
{
return ele1.C < ele2.C;
}
//부모 찾기
int get_parent(int parents[], int target)
{
if(parents[target] == target) return target;
return parents[target] = get_parents(parents, parents[target]);
}
//유니온 파인드 (순환이 검색되면 False)
bool set_union(int parents[], int a, int b)
{
a = get_parent(parents, a);
b = get_parent(parents, b);
if (a == b) return false;
parents[a] = b;
return true;
}
int main()
{
int V, E;
scanf("%d %d", &V, &E);
vector<ABC> graph;
int* parents = new int[V];
for (int i = 0; i < V; i++) parents[i] = i;
//입력부
for (int i = 0; i < E; i++)
{
int a, b, c; //A -> B (Cost)
scanf("%d %d %d", &a, &b, &c);
a--; b--;
ABC input;
input.A = a;
input.B = b;
input.C = c;
graph.push_back(input);
}
sort(graph.begin(), graph.end(), cmp);
long long result = 0;
//크루스칼
for (ABC edge : graph)
{
if (set_union(parents, edge.A, edge.B)) result += edge.C;
}
printf("%lld", result);
delete[] parents;
return 0;
}
그 외
'공부 및 정리 > 백준 코드' 카테고리의 다른 글
[C++]백준 - 1774번 문제 (0) | 2021.10.26 |
---|---|
[C++]백준 - 4386번 문제 (0) | 2021.10.26 |
[C++]백준 - 11780번 문제 (0) | 2021.10.25 |
[C++]백준 - 20040번 문제 (0) | 2021.10.24 |
[C++]백준 - 1100번 문제 (0) | 2021.10.24 |