카테고리 없음

[SWEA][JAVA] 1251. [S/W 문제해결 응용] 4일차 - 하나로

갱스타 2022. 3. 1. 00:59

하나로

 


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

//크루스칼 방법으로 풀고, 모든 간선의 크기를 계산해서 오름차순으로 정렬한다.결국에는 조합-> 비트마스킹을 이용한 조합
public class Solution{
    static List<Edge> list;
    static int N;
    static int[] subset;
    static double E;
    static int[] Parent;
    static class Edge implements Comparable<Edge>{
        int from, to;
        double weight;
        public Edge(int start, int end, double weight) {
            this.from = start;
            this.to = end;
            this.weight = weight;
        }
        @Override
        public int compareTo(Edge o) {
            double result=(this.weight-o.weight);
            if(result<0) return-1;
            else return 1;
        }
    }
    public static void main(String[] args) throws IOException {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());
        int T=Integer.parseInt(st.nextToken());
        //테스트케이스
        for (int tc = 1; tc <=T ; tc++) {
            st=new StringTokenizer(br.readLine());
            N=Integer.parseInt(st.nextToken());
            //각각 정점의 번호를 x의 index와 같다고 한다.
            long[][] map=new long[N][2];

            //간선을 저장할 Edge리스트를 생성한다.
            list=new LinkedList<>();
            subset=new int[2];
           Parent=new int[N];
            //x좌표 입력받기
            st=new StringTokenizer(br.readLine());
            for (int i = 0; i < N ; i++) {
                map[i][0]=Long.parseLong(st.nextToken());
            }
            //y좌표 입력받기
            st=new StringTokenizer(br.readLine());
            for (int i = 0; i < N; i++) {
                map[i][1]=Long.parseLong(st.nextToken());
            }
            st=new StringTokenizer(br.readLine());
            E=Double.parseDouble(st.nextToken());
            //간선리스트 완성
            combi(map,0,0);
            //간선리스트 정렬
            Collections.sort(list);
            makeSubset();
            double result=0;
            int cnt=0;
            for (Edge e:list) {
                if(union(e.from,e.to)){
                    ++cnt;
                    result+= e.weight;
                }
                if(cnt==N-1)
                    break;;
            }
            System.out.printf("#%d %d%n",tc,Math.round(result));
        }
    }

    private static boolean union(int from, int to) {
        int fromParent=findParent(from);
        int toParent=findParent(to);
        if(toParent==fromParent) return false;
        Parent[toParent]=fromParent;
        return true;
    }

    private static int findParent(int from) {
        if(from==Parent[from]) return from;
        return Parent[from]=findParent(Parent[from]);
    }
    private static void makeSubset() {
        for (int i = 0; i < N; i++) {
            Parent[i]=i;
        }
    }
    private static void combi(long[][] map, int start, int cnt) {
        if(cnt==2){
            double weight=(Math.pow(Math.abs(map[subset[0]][0]-map[subset[1]][0]),2)+
                    Math.pow(Math.abs(map[subset[0]][1]-map[subset[1]][1]),2))*
                    E;
            list.add(new Edge(subset[0],subset[1],weight));
            return;
        }
        for (int i = start; i < N; i++) {
            subset[cnt]=i;
            combi(map,i+1,cnt+1);
        }

    }
}