백준공부/java

[백준] 1774번 우주신과의 교감 (gold 3

gomduri43 2024. 1. 10. 12:12

import java.io.*;
import java.util.*;

class Point{
    double x;
    double y;
    public Point(double x, double y){
        this.x=x;
        this.y=y;
    }
}

class Input{
    int x;
    double y;
    public Input(int x, double y){
        this.x=x;
        this.y=y;
    }
}
public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));

        StringTokenizer st=new StringTokenizer(br.readLine());
        int n=Integer.valueOf(st.nextToken());
        int m=Integer.valueOf(st.nextToken());

        Point[] uni=new Point[n+1];
        for(int i=1; i<=n; i++){
            st=new StringTokenizer(br.readLine());
            uni[i]=new Point(Double.valueOf(st.nextToken()) , Double.valueOf(st.nextToken()));
        }//각 좌표들

        ArrayList<Integer>[] link=new ArrayList[n+1];
        for(int i=1; i<=n; i++){
            link[i]=new ArrayList<>();
        }//연결되어 있는 케이스들

        for(int i=1; i<=m; i++){
            st=new StringTokenizer(br.readLine());
            int a=Integer.valueOf(st.nextToken());
            int b=Integer.valueOf(st.nextToken());
            link[a].add(b);
            link[b].add(a);
        }

        PriorityQueue<Input> que=new PriorityQueue<>(new Comparator<Input>(){
            public int compare(Input o1, Input o2){
                if(o1.y==o2.y){
                    return o1.x-o2.x;
                }
                else {
                    return (int) ((o1.y - o2.y) * 1000);
                }
            }
        });

        double answer=0;
        boolean[] visit=new boolean[n+1];

        que.offer(new Input(1,0));

        while(!que.isEmpty()){
            Input temp=que.poll();
            if(visit[temp.x]){
                continue;
            }
            visit[temp.x]=true;
            answer+=temp.y;

            for(int i=0; i<link[temp.x].size(); i++){
                if(visit[link[temp.x].get(i)]){
                    continue;
                }
                que.offer(new Input(link[temp.x].get(i) , 0.0));
            }

            for(int i=1; i<=n; i++){
                if(visit[i]){
                    continue;
                }
                double l=Math.sqrt(Math.pow(uni[temp.x].x-uni[i].x,2) + Math.pow(uni[temp.x].y-uni[i].y ,2));
                que.offer(new Input(i, l));
            }
        }
        answer=(double)((int)(Math.round(answer*100)))/100;
        bw.write(String.format("%.2f" , (answer)));
        bw.flush();
    }
}

// 이미 연결되어 있는 경우가 있는 상황에서 연결 안 된 노드들의 mst를 구하는 문제이다
// 각 좌표의 값을 저장하고, 이미 연결되어 있는 연결점들도 저장한다.
// mst를 돌면서 이미 연결된 경우는 거리를 0으로, 나머지 연결점들은 거리값을 que에 넣어주면서
// mst를 구하면된다. 이때 고려할 점은 priorityQueue에서의 comparator였다.
// 총 3번 정도 틀렸는데, 그 문제를 파악해보니. 우선순위큐에서의 우선순위 판단에서. 
// return (int) (o1.y - o2.y) * 10; 이부분이 오류였다.
// 왜냐하면 (int)형변환은 뒤에 (o1.y - o2.y)까지이기 때문이다. 그래서 만약 소수점의 차이가 존재하면.
// (int)형변환으로 0이되어 같은 값으로 판별된다. 따라서, return (int) ((o1.y - o2.y) * 1000);
// 다음처럼 전체를 괄호로 묶어야 올바르게 크기 판단이 이루어진다.