Notice
Recent Posts
문제 풀이 및 개발 공간
[백준] 2887번 행성 터널 (platinum 5 본문
import java.io.*;
import java.util.*;
class Point{
int n;
int v;
public Point(int n,int v){
this.n=n;
this.v=v;
}
}
class Node{
int n1;
int n2;
int v;
public Node(int n1, int n2, int v){
this.n1=n1;
this.n2=n2;
this.v=v;
}
}
public class Main{
static int[] num;
public static void main(String[] args) throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
int t=Integer.valueOf(br.readLine());
//x,y,z별로 정렬 이유는 x,y,z의 값의 차이에 따라 mst에 추가해야함.
//정렬을 해서 차이가 적게 나는 경우부터 추가하는게 편함
PriorityQueue<Point> qx=new PriorityQueue<>(new Comparator<Point>(){
public int compare(Point o1, Point o2){
return o1.v-o2.v;
}
});
PriorityQueue<Point> qy=new PriorityQueue<>(new Comparator<Point>(){
public int compare(Point o1, Point o2){
return o1.v-o2.v;
}
});
PriorityQueue<Point> qz=new PriorityQueue<>(new Comparator<Point>(){
public int compare(Point o1, Point o2){
return o1.v-o2.v;
}
});
PriorityQueue<Node> que=new PriorityQueue<>(new Comparator<Node>(){
public int compare(Node o1, Node o2){
return o1.v-o2.v;
}
});
StringTokenizer st;
for(int i=1; i<=t; i++){
st=new StringTokenizer(br.readLine());
int x=Integer.valueOf(st.nextToken());
int y=Integer.valueOf(st.nextToken());
int z=Integer.valueOf(st.nextToken());
qx.offer(new Point(i,x));
qy.offer(new Point(i,y));
qz.offer(new Point(i,z));
}
int tv=0;
int tn=0;
//정점끼리의 차를 que에 추가하기. 즉 간선추가.
Point p=qx.poll();
tv=p.v;
tn=p.n;
while(!qx.isEmpty()){
p=qx.poll();
que.offer(new Node(tn, p.n, Math.abs(tv-p.v)));
tv=p.v;
tn=p.n;
}
p=qy.poll();
tv=p.v;
tn=p.n;
while(!qy.isEmpty()){
p=qy.poll();
que.offer(new Node(tn, p.n, Math.abs(tv-p.v)));
tv=p.v;
tn=p.n;
}
p=qz.poll();
tv=p.v;
tn=p.n;
while(!qz.isEmpty()){
p=qz.poll();
que.offer(new Node(tn, p.n, Math.abs(tv-p.v)));
tv=p.v;
tn=p.n;
}
long answer=0;
int planet=0;
num=new int[t+1];
for(int i=1; i<=t; i++){
num[i]=i;
}
if(que.size()==0){
System.out.println(0);
}
else{
//유니온 파인드로 정점들간에 중복. 혹은 겹치는 경우를 제외하고 추가한다.
while(!que.isEmpty()){
Node temp=que.poll();
if(Find(temp.n1) == Find(temp.n2)){
continue;
}
Union(temp.n1,temp.n2);
answer+=temp.v;
planet++;
if(planet==t-1){
break;
}
}
bw.write(answer+"");
bw.flush();
}
}
public static int Find(int a){
if(a==num[a]){
return a;
}
else return num[a]=Find(num[a]);
}
public static void Union(int a, int b){
int fa=Find(a);
int fb=Find(b);
if(fa!=fb){
num[fa]=fb;
}
}
}
//이 문제는 다 생각해내고 마지막에서 헤매게 되었다.
//이유는 정점들 간의 경로에서 문제가 생겼는데, mst를 prim으로만 해결하다보니 union-find구현,
//정확한 적용을 모르고 있었다. prim으로 해결할 수 있을 것 같지만 출발점에서 다른 점으로 가다가, 다른 점에서
//출발점으로 들어올 때, 또 이런 경우가 여러번 발생가능. 이를 분류하는게 prim으로는 너무 복잡했고,
//결국 union-find개념을 익히고 해결하니 간단하게 해결되었다.
'백준공부 > java' 카테고리의 다른 글
[백준] 2535번 아시아 정보올림피아드 (silver 5 (0) | 2024.03.13 |
---|---|
[백준] 1976번 여행 가자 (gold 4 (0) | 2024.03.13 |
[백준] 37474번 양갈래 짝 맞추기 (silver 4 (0) | 2024.03.12 |
[백준] 31472번 갈래의 색종이 자르기 (bronze 3 (0) | 2024.03.12 |
[백준] 1766번 문제집 (gold 2 (3) | 2024.03.12 |