1414 : 불우이웃돕기

풀이

미니멈 스패닝 트리를 쓰자.

크루스칼을 쓰자.

전체 랜선의 합에서 최소로 잇는 랜선의 합을 빼주자.

자잘한 처리가 조금 귀찮은 문제다.

코드

#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;

struct edg {
	int x, y, w;
	edg(int x, int y, int w) :x(x), y(y), w(w) {}
	bool operator <(edg A)const { return w < A.w; }
};

int n, pnt[101];
vector<edg> gph;

int find(int u) {
	if (u == pnt[u]) return u;
	return pnt[u] = find(pnt[u]);
}

void merge(int u, int v) {
	u = find(u), v = find(v);
	if (pnt[u] == pnt[v]) return;
	if (u > v) swap(u, v);
	pnt[u] = v;
}

int main() {
	int i, j, sum1 = 0, sum2 = 0;
	char str[101];
	scanf("%d", &n);
	for (i = 0; i < n; i++) pnt[i] = i;
	for (i = 0; i < n; i++) {
		scanf("%s", str);
		for (j = 0; j < n; j++) {
			int tmp = (int)str[j] + 1;
			if (str[j] >= 'a' && str[j] <= 'z') tmp -= 'a';
			if (str[j] >= 'A' && str[j] <= 'Z') tmp -= 'A' - 26;
			if (str[j] != '0') {
				sum1 += tmp;
				if (i != j) gph.push_back(edg(i, j, tmp));
			}
		}
	}
	sort(gph.begin(), gph.end());
	int cnt = 1;
	for (auto now : gph) {
		int x = now.x, y = now.y, w = now.w;
		if (find(x) != find(y)) merge(x, y), sum2 += w, cnt++;
	}
	if (cnt < n) printf("-1");
	else printf("%d", sum1 - sum2);

	return 0;
}

아무말

백준, 백준 온라인 저지, BOJ, Baekjoon Online Judge

wookje.kwon's profile image

wookje.kwon

2017-04-21 09:01

Read more posts by this author