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;
}