https://www.acmicpc.net/problem/10423

 

MST 크루스칼 문제고 잘 풀었다.

근데 티어 높은 다른 사람들 코드 보니까 좀 특이해서 아이디어 남겨둔다.

 

위의 이중원은 발전소고 단일원은 도시인데 하나의 도시 묶음에 발전소 2개가 들어가면 안된다.

그래서 난 Union할때 발전소 번호로 묶어줬고

Union하기 전에 둘 다 발전소 번호면 묶지 않게 조건 달아줬다.

그래서 잘 풀었다.

 

근데 다른 사람들 코드 보니 시작하자 마자 발전소 3개끼리 묶어버린다.

이러면 다른 도시들이 또 다른 발전소랑 그룹지으려 하면 사이클이 생기니 안묶는다.

되게 간단하고 신기한 아이디어다.

 

내 코드 남겨둔다. 

만약 발전소끼리 묶고 시작한다면 Union함수도 건들 필요 없고 if문도 깔끔했을 듯 하다.

#include <bits/stdc++.h>
using namespace std;

vector<int> parent;
vector<bool> power_plant;

int Find(int x)
{
	if (parent[x] == x) return x;
	return parent[x] = Find(parent[x]);
}

void Union(int x, int y)
{
	x = Find(x);
	y = Find(y);
	if (power_plant[x]) parent[y] = x;
	else if (power_plant[y]) parent[x] = y;
	else {
		if (x < y) parent[y] = x;
		else if (x > y) parent[x] = y;
	}
}

int main()
{
	ios::sync_with_stdio(false); cin.tie(NULL);

	int N, M, K; // 도시갯수, 케이블수, 발전소수
	cin >> N >> M >> K;

	power_plant.resize(N + 1, false);
	int input;
	for (int i = 0; i < K; i++) {
		cin >> input;
		power_plant[input] = true;
	}

	parent.resize(N + 1);
	for (int i = 1; i < N + 1; i++) {
		parent[i] = i;
	}

	vector<tuple<int, int, int>> costs(M); // cost, from, to
	int u, v, w;
	for (int i = 0; i < M; i++) {
		cin >> u >> v >> w;
		costs[i] = { w, u, v };
	}
	sort(costs.begin(), costs.end());

	int answer = 0, count = 0;
	for (auto t : costs) {
		int cost = get<0>(t);
		int from = get<1>(t);
		int to = get<2>(t);

		if (Find(from) != Find(to) && !(power_plant[parent[from]] && power_plant[parent[to]])) {
			answer += cost;
			Union(from, to);
			count++;
		}

		if (count == N - 1) break;
	}

	cout << answer;

	return 0;
}