[白俊-Java]1774号:宇宙神との交感
質問する
https://www.acmicpc.net/problem/1774
説明:
クルーズアルゴリズムを用いて問題を解決した.
注意事項
接続された神々とのチャネルを入力するとunionが行われ、unionメソッドでfind演算を実行する必要があります.
以前,最小生成ツリー問題を解いたとき,クルーズアルゴリズムを実行する部分で特定の幹線の始点,終点の最上位ノードを見つけ,union法では単独find演算を行わずにノードの親ノードを直接変更した.
しかし,この問題ではクルーズアルゴリズムを実行する部分でもunionを実行するが,接続されたチャネルを入力する際にもunionを実行するので,unionメソッドでfind演算を実行しないと不正確な答えが出る可能性がある.
下図のようにunionメソッドを記述すればよい.
https://github.com/MinchaeGwon/BOJ/blob/master/BOJ%231774/src/Main.java
https://www.acmicpc.net/problem/1774
説明:
クルーズアルゴリズムを用いて問題を解決した.
注意事項
接続された神々とのチャネルを入力するとunionが行われ、unionメソッドでfind演算を実行する必要があります.
以前,最小生成ツリー問題を解いたとき,クルーズアルゴリズムを実行する部分で特定の幹線の始点,終点の最上位ノードを見つけ,union法では単独find演算を行わずにノードの親ノードを直接変更した.
しかし,この問題ではクルーズアルゴリズムを実行する部分でもunionを実行するが,接続されたチャネルを入力する際にもunionを実行するので,unionメソッドでfind演算を実行しないと不正確な答えが出る可能性がある.
下図のようにunionメソッドを記述すればよい.
public static boolean union(int x, int y) {
x = find(x);
y = find(y);
// 최상위 노드가 같지 않을 경우 union
if (x != y) {
parent[x] = y;
return true;
}
return false;
}
ソースコードimport java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
class Edge implements Comparable<Edge> {
int s;
int e;
double weight;
public Edge(int s, int e, double weight) {
this.s = s;
this.e = e;
this.weight = weight;
}
@Override
public int compareTo(Edge e) {
return Double.compare(this.weight, e.weight);
}
}
public class Main {
static int[] parent;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken()); // 우주신들의 개수
int M = Integer.parseInt(st.nextToken()); // 연결된 신들과의 통로의 개수
int[][] god = new int[N + 1][2]; // 우주신의 좌표 저장
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
god[i][0] = Integer.parseInt(st.nextToken());
god[i][1] = Integer.parseInt(st.nextToken());
}
parent = new int[N + 1];
// 부모를 자기 자신으로 초기화
for (int i = 1; i <= N ; i++) {
parent[i] = i;
}
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int s = Integer.parseInt(st.nextToken());
int e = Integer.parseInt(st.nextToken());
union(s, e); // 이미 연결된 통로는 union을 통해 합침
}
PriorityQueue<Edge> pq = new PriorityQueue<>();
// 연결할 수 있는 모든 통로를 큐에 추가
for (int i = 1; i < N; i++) {
for (int j = i + 1; j < N + 1; j++) {
int x1 = god[i][0];
int y1 = god[i][1];
int x2 = god[j][0];
int y2 = god[j][1];
double weight = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
pq.add(new Edge(i, j, weight));
}
}
double result = 0;
// 크루스칼 알고리즘 이용
while (!pq.isEmpty()) {
Edge edge = pq.poll();
// 통로의 시작점과 끝점의 그룹을 합침(최상위 노드가 다를 경우)
if (union(edge.s, edge.e)) {
result += edge.weight; // 가중치를 더함
}
}
System.out.println(String.format("%.2f", result));
}
// x가 속하는 부모 노드(최상위 노드)를 찾음
public static int find(int x) {
if (parent[x] == x) {
return x;
}
else {
return parent[x] = find(parent[x]);
}
}
// 두 개의 노드가 속한 집합을 합침(연결함)
public static boolean union(int x, int y) {
// 통로의 시작점과 끝점의 최상위 노드를 찾음
x = find(x);
y = find(y);
// 최상위 노드가 같지 않을 경우 union
if (x != y) {
parent[x] = y;
return true;
}
return false;
}
}
GITHUBhttps://github.com/MinchaeGwon/BOJ/blob/master/BOJ%231774/src/Main.java
Reference
この問題について([白俊-Java]1774号:宇宙神との交感), 我々は、より多くの情報をここで見つけました https://velog.io/@minchae75/백준-Java-1774번-우주신과의-교감テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol