-마을을 두 개로 분할한다
- 분리된 두 마을 사이 길은 필요없다
- 마을 안에서 임의의 두 집 사이 경로는 항상 존재
- 마을에는 집이 하나 이상 있어야 한다
- 길의 유지비는 최소
으음..... 마을을 두 개로 어떻게 나눠야 할지 모르겠다.
마을을 나누기 위해서 다리를 1개를, 2개를 등등 여러 개 끊을 수 있는데 이걸 어떻게 나눠야하지?
그러곤 알고리즘 방에 질문 올리고 그래프로 더 그려보면서 생각했는데 방법이 떠올랐다.
MST를 그리면 최소 간선들만 남는다. (나는 다각형이 나올거라 착각했다)
그럼 그 최소 중 하나만 잘라내면 마을을 두 개로 분리할 수 있다. 그 하나가 최대인 걸 잘라야 하는 거고...
허....
뭔가 반으로 나누면서 길을 없앨 수 있고 -> 그럼 반으로 나눌 때 최대한 많은 길을 잘라야겠다!
여기서 막혔던 것 같다.
코드는 이렇다.
이제 유파는 다 외움! 블로그 코드 안 보고 빠르게 짰다. 뿌듯
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <functional>
#include <string>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cmath>
#include <cstring>
#include <bitset>
#include <stdio.h>
#include <math.h>
#include <sstream>
#define xx first
#define yy second
#define all(x) (x).begin(), (x).end()
using namespace std;
using i64 = long long int;
using ii = pair<int, int>;
using iis = pair<int, string>;
using ii64 = pair<i64, i64>;
using iii = tuple<int, int, int>;
struct Edge {
int u, v, d;
};
int par[100005];
int find(int x) {
if (x == par[x])
return x;
return par[x] = find(par[x]);
}
void init(int n) {
for (int i = 1; i <= n; i++) {
par[i] = i;
}
}
void merge(int x, int y) {
x = find(x);
y = find(y);
par[x] = y;
}
int main() {
int n, m;
scanf("%d %d", &n, &m);
init(n);
vector<Edge> edge(m);
for (int i = 0; i < m; i++)
scanf("%d %d %d", &edge[i].u, &edge[i].v, &edge[i].d);
sort(all(edge), [](const Edge &l, const Edge &r){
return l.d < r.d;
});
int ans = 0;
int maxRoad = 0;
for (int i = 0; i < edge.size(); i++) {
if (find(edge[i].u) == find(edge[i].v))
continue;
ans += edge[i].d;
maxRoad = max(maxRoad, edge[i].d);
merge(edge[i].u, edge[i].v);
}
printf("%d\n", ans - maxRoad);
return 0;
}
'백준' 카테고리의 다른 글
16398 행성 연결 (0) | 2022.08.20 |
---|---|
13905 세부 (0) | 2022.08.10 |
1197 최소 스패닝 트리 (0) | 2022.08.08 |
9226 도깨비말 (0) | 2022.07.31 |
14615 Defend the CTP!!! (0) | 2022.07.30 |