algorithm/그래프

Boj 13418

아르비스 2019. 10. 17. 18:07

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

 

13418번: 학교 탐방하기

입력 데이터는 표준 입력을 사용한다. 입력은 1개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 건물의 개수 N(1≤N≤1,000)과 도로의 개수 M(1≤M≤n*(n-1)/2) 이 주어진다. 입력의 두 번째 줄부터 M+1개의 줄에는 A, B(1≤ A,B ≤ N), C 가 주어진다. 이는 A와 B 건물에 연결된 도로가 있다는 뜻이며, C는 0(오르막길) 또는 1(내리막길)의 값을 가진다. 같은 경로 상에 2개 이상의 도로가 주어지는 경우는 없으며, 입

www.acmicpc.net

 

문제를 이해하는데 한참 걸렸다.

그냥 MST(크루스칼)로 푸는 문제인데..

 

단 예외 조건이 있다, 오르막이 0, 내리막이 1로 제공된다.

따라서, 1-C (0->1 / 1->0)  으로 적용해야 한다.

또한 "입력받은 데이터에 대해, 주어진 조건을 만족하는 최악의 경로에서의 피로도와 최적의 경로 간 피로도의 차이를 출력한다." 라고 한다.

아래 문구가 젤 중요하다.

오르막길을 k번 오를 때, 피로도는 k2이 된다. 피로도의 계산은 최초 조사된 길을 기준으로만 한다. 즉, 내리막길로 내려갔다 다시 올라올 때 오르막길이 되는 경우는 고려하지 않는다

 

암튼 문제가 푸는게 어려운게 아니라, 문제를 이해하는게 어렵다.

 

import java.io.*;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class boj13418 {
    static int N, M;
    static DJS djs;
    static Node[] nodes;
    static class Node {
        int s, e, v;
        Node(int s, int e, int v) {
            this.s = s;
            this.e = e;
            this.v = v;
        }
    }
    static class DJS {
        int[] mom;
        DJS(int n) {
            mom = new int[n+1];
            for (int i = 1; i <= n; i++) mom[i] = i;
        }
        int find(int n) {
            return (n==mom[n])? n : (mom[n] = find(mom[n]));
        }

        boolean union(int a, int b) {
            a = find(a);
            b = find(b);
            if(a==b) return false;
            mom[b] = a;
            return true;
        }
    }
    public static void main(String[] args) throws IOException {
        System.setIn(new FileInputStream("res/input_boj13418.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine().trim(), " ");
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        djs = new DJS(N);
        nodes = new Node[M+1];

        int a, b ,c;
        for (int i = 0; i < M+1 ; i++) {
            st = new StringTokenizer(br.readLine().trim(), " ");
            a = Integer.parseInt(st.nextToken());
            b = Integer.parseInt(st.nextToken());
            c = Integer.parseInt(st.nextToken());
            nodes[i] = new Node(a, b, 1-c);
        }

        // Kruskal
        Comparator<Node> cmp = (o1, o2) -> o1.v - o2.v;
        Arrays.sort(nodes, cmp);

        long max = 0;
        long min = 0;
        for (int i = 0; i < M+1 ; i++) {
            if(djs.union(nodes[i].s, nodes[i].e)) {
                min += nodes[i].v;
            }
        }

        cmp = (o1,o2) -> o2.v - o1.v;
        Arrays.sort(nodes, cmp);
        djs = new DJS(N);
        for (int i = 0; i < M+1 ; i++) {
            if(djs.union(nodes[i].s, nodes[i].e)) {
                max += nodes[i].v;
            }
        }

        System.out.println((max*max) - (min*min));
    }
}