https://www.acmicpc.net/problem/1647
해당 문제는 최소 신장 트리(MST) 문제로, 모든 섬을 연결하는 최소 신장 트리를 만든 후에 최소 신장 트리를 구성하는 간선 중 가장 가중치가 큰 간선을 없애면 마을을 두 개로 분할 가능하고, 두 마을의 간선의 가중치 합도 최소로 유지할 수 있다. 이 문제에서는 MST를 구하기 위해 크루스칼 알고리즘을 사용했다.
1) 사이클 테이블에 각 노드(섬)들의 부모를 자기 자신으로 지정한다.
2) 간선들의 정보를 저장하는 벡터 edges
를 만들어 각 간선들의 (가중치, 노드 a, 노드 b)를 저장한다.
3) edges
를 가중치의 오름차순으로 정렬한다.
4) 정렬된 벡터에 대해 크루스칼 알고리즘을 적용한다.
answer
에 간선의 가중치를 누적시킨다.5) 크루스칼 알고리즘이 종료되면 answer
에는 간선들의 최소 가중치합이 저장되는데, 이 때 여기서 maxCost를 빼주면 두 개로 분할된 마을의 간선들의 최소 가중치합이 나오게 된다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <tuple>
#include <queue>
using namespace std;
typedef tuple<int, int, int> tiii;
int parent[100001];
int getParent(int n)
{
if (parent[n] == n) return n;
return parent[n] = getParent(parent[n]);
}
void unionParent(int a, int b)
{
a = getParent(a);
b = getParent(b);
if (a < b)
parent[b] = a;
else
parent[a] = b;
}
bool findParent(int a, int b)
{
a = getParent(a);
b = getParent(b);
return (a == b);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
int n, m;
cin >> n >> m;
for (int i = 0; i <= n; i++)
parent[i] = i;
vector<tiii> edges;
for (int i = 0; i < m; i++)
{
int a, b, c;
cin >> a >> b >> c;
edges.push_back(tiii(c, a, b));
}
sort(edges.begin(), edges.end());
long long answer = 0;
int maxCost = 0;
for (int i = 0; i < edges.size(); i++)
{
int curA = get<1>(edges[i]);
int curB = get<2>(edges[i]);
int curC = get<0>(edges[i]);
if (!findParent(curA, curB))
{
unionParent(curA, curB);
answer += curC;
if (curC > maxCost)
maxCost = curC;
}
}
cout << answer - maxCost;
}