https://www.acmicpc.net/problem/14950
해당 문제는 최소 신장 트리(MST) 문제로, 모든 노드(== 도시)에서 다른 모든 노드로 향하는 간선이 있다고 가정하고, 이 간선들에 대해 크루스칼 알고리즘을 사용하여 모든 노드들이 이어지되, 이어지는 간선들의 가중치의 합이 최소가 되는 경우를 구해야 한다. 단, 도시가 하나 이어질 때마다 가중치가 증가하는 부분을 고려해야 한다.
1) 모든 노드들 사이에 존재하는 간선에 대한 tuple(두 노드 간 가중치, 노드A 번호, 노드B 번호)들을 저장하는 벡터인 edges
에 모든 노드에서 다른 모든 노드로 향하는 간선에 대한 가중치를 계산해 저장한다.
2) edges
벡터에 대해 크루스칼 알고리즘을 적용한다.
edges
벡터를 가중치의 오름차순으로 정렬한다.sum
에 해당 간선의 가중치 + (t
* count
)를 누적한다.sum
: mst를 이루는 모든 간선의 가중치의 합count
: 지금까지 정복한 도시의 개수count
를 하나 증가시킨다.3) 위 크루스칼 알고리즘 과정이 끝나면 sum
에 모든 도시를 정복하는 데에 필요한 최소 비용이 저장된다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <tuple>
using namespace std;
typedef tuple<int, int, int> tiii;
int n, m, t;
vector<tiii> edges;
int parent[10001];
int getParent(int n)
{
if (parent[n] == n)
return n;
else
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(nullptr); cout.tie(nullptr);
cin >> n >> m >> t;
for (int i = 0; i < m; i++)
{
int a, b, c;
cin >> a >> b >> c;
edges.push_back(tiii(c, a, b));
edges.push_back(tiii(c, b, a));
}
sort(edges.begin(), edges.end());
for (int i = 1; i <= n; i++)
parent[i] = i;
int sum = 0;
int count = 0;
for (int i = 0; i < edges.size(); i++)
{
int curA = get<1>(edges[i]);
int curB = get<2>(edges[i]);
if (!findParent(curA, curB))
{
unionParent(curA, curB);
sum += get<0>(edges[i]);
sum += t * count;
count++;
}
}
cout << sum;
}