728x90
https://www.acmicpc.net/problem/1647
1647번: 도시 분할 계획
첫째 줄에 집의 개수N, 길의 개수M이 주어진다. N은 2이상 100,000이하인 정수이고, M은 1이상 1,000,000이하인 정수이다. 그 다음 줄부터 M줄에 걸쳐 길의 정보가 A B C 세 개의 정수로 주어지는데 A번 집
www.acmicpc.net
전형적인 최소 신장 트리 문제였다. 문제를 읽자마자 최소 신장 트리를 구현하는데 좋은 예제라는 것을 알았다..ㅎ 하지만 조금 응용된 것이 마을 두 개를 분리하는데 길 유지비의 합의 최소값을 구하라고 하였다. 즉, 최소 신장 트리를 구한 다음에 제일 거리가 긴 곳을 없애면 된다. 하나의 길을 없애면 두 개의 마을이 생기는 거니까!
parent 노드를 찾는 함수랑 노드를 합치는 함수를 이용하여 구현하였다. 이것이 코딩테스트다 10장에서 연습했던 전형적인 크루스칼 알고리즘을 사용한 후에 각각의 길을 result 벡터에 입력시켰다. 그 후에 가장 마지막( 제일 거리가 긴 곳) 을 빼주면 두 개의 분리된 마을의 길 유지비의 합이 최소가 된다!
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<pair<int, pair<int, int>>> arr;
int parent[100001];
vector<int> result;
int node_parent(int x)
{
if (x == parent[x])
return x;
else
return parent[x] = node_parent(parent[x]);
}
void Union_node(int x, int y)
{
x = node_parent(x);
y = node_parent(y);
if (x > y)
{
parent[x] = y;
}
else
{
parent[y] = x;
}
}
int main()
{
int N, M;
cin >> N >> M;
for (int i = 0; i < M; i++)
{
int a, b, c;
cin >> a >> b >> c;
//비용순으로 오름차순
arr.push_back({ c, { a,b } });
}
for (int i = 1; i <= N; i++)
{
parent[i] = i;
}
sort(arr.begin(), arr.end());
for (int i = 0; i < M; i++)
{
int a = node_parent(arr[i].second.first);
int b = node_parent(arr[i].second.second);
if (a != b)
{
Union_node(a, b);
result.push_back(arr[i].first);
}
}
int sum = 0;
for (int i = 0; i < result.size() - 1; i++)
{
sum += result[i];
}
cout << sum;
}
'알고리즘 > 알고리즘 문제' 카테고리의 다른 글
[백준] 14502 연구소 (0) | 2021.08.26 |
---|---|
[백준] 18352 특정 거리의 도시 찾기 (0) | 2021.08.25 |
[백준] 2839번 - 설탕 배달 (0) | 2021.08.22 |
[이것이 코딩테스트다] 다이나믹 프로그래밍 - 개미 전사 (0) | 2021.08.22 |
[백준] 1439번 - 뒤집기 (0) | 2021.08.22 |