본문 바로가기

백준

1647 도시 분할 계획

-마을을 두 개로 분할한다

- 분리된 두 마을 사이 길은 필요없다

- 마을 안에서 임의의 두 집 사이 경로는 항상 존재

- 마을에는 집이 하나 이상 있어야 한다

- 길의 유지비는 최소

 

 

으음..... 마을을 두 개로 어떻게 나눠야 할지 모르겠다. 

마을을 나누기 위해서 다리를 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