1774๋ฒ: ์ฐ์ฃผ์ ๊ณผ์ ๊ต๊ฐ
LV : ๊ณจ๋ 3
ํด๋น ๋ฌธ์ ๋ ์ต์์ ์ฅํธ๋ฆฌ(MST)๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค.
MST๋ฅผ ๋ง๋๋ ์๊ณ ๋ฆฌ์ฆ์ ํฌ๋ฃจ์ค์นผ๊ณผ ํ๋ฆผ ์๊ณ ๋ฆฌ์ฆ์ด ์๋๋ฐ, ์ฌ๊ธฐ์์๋ ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ์ ์จ๋ณด๊ธฐ๋ก ํ๋ค.
์ด ๋ฌธ์ ๊ฐ ์ผ๋ฐ์ ์ธ ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ๊ณผ ๋ค๋ฅธ ์ ์ ์ด๋ฏธ ์ฐ๊ฒฐ๋ ๊ฐ์ ์ ๋ณด๊ฐ ์๋ค๋ ์ ์ด๋ค.
์์น๊ฐ x, y ์ขํ๋ก ๋์ค๊ธฐ ๋๋ฌธ์ Node ํด๋์ค๋ฅผ ์์ฑํด์ค๋ค.
class Node {
long x, y;
public Node(long x, long y) {
this.x = x;
this.y = y;
}
}
ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ์ ์ํด์๋ ๊ฐ์ค์น๊ฐ ์ ์ ๊ฐ์ ๋ถํฐ ์ ํํด์ผ ํ๊ธฐ ๋๋ฌธ์ Comparable์ ์ ์ฉํด์ค๋ค.
class Edge implements Comparable<Edge> {
int from, to;
double w;
public Edge(int from, int to, double w) {
this.from = from;
this.to = to;
this.w = w;
}
@Override
public int compareTo(Edge o) {
// double ๋น๊ต ์ ์ค์ฐจ ๋ฌธ์ ๋๋ฌธ์ Math.signum()์ ์ฌ์ฉํ๋ ๊ฒ์ด ์์
return Double.compare(this.w, o.w);
}
}
// 1. ์ด๊ธฐ ์ค์
parent = new int[N + 1];
// ๋ถ๋ชจ ๋ฐฐ์ด ์ด๊ธฐํ
for (int i = 1; i < N + 1; i++) {
parent[i] = i;
}
// 2. ์ขํ๊ฐ ์ ์ฅ
List<Node> spots = new ArrayList<>(N + 1);
spots.add(null);// 0๋ฒ์งธ๋ ๋น์ด๋๊ธฐ
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
long x = Long.parseLong(st.nextToken());
long y = Long.parseLong(st.nextToken());
spots.add(new Node(x, y));
}
union-find๋ก ์งํฉ์ ๋ฌถ์ด์ค๋ค.
int edgesCount = 0; // ์ ํ๋ ๊ฐ์ ์ ๊ฐ์
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int from = Integer.parseInt(st.nextToken());
int to = Integer.parseInt(st.nextToken());
if (union(from, to)) {
edgesCount++;
}
}
// 4. ๋ชจ๋ ๊ฐ๋ฅํ ๊ฐ์ ์ ๋ณด ์์ฑ
List<Edge> edges = new ArrayList<>();
// ๊ฐ์ ์ ๋ณด ์ ์ฅ
for (int i = 1; i <= N; i++) {
for (int j = i + 1; j <= N; j++) {
double weight = getDistance(spots.get(i), spots.get(j));
// Edge ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋ฆฌ์คํธ์ ์ถ๊ฐ
edges.add(new Edge(i, j, weight));
}
}
// 5. ๊ฐ์ ์ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌ
Collections.sort(edges);
double minTotalWeight = 0; // ์๋ก ๋ง๋ค์ด์ผ ํ ํต๋ก์ ์ต์ ๊ธธ์ด ํฉ
int edgesCount = 0; // ์ ํ๋ ๊ฐ์ ์ ๊ฐ์
for (Edge edge : edges) {
// ์ฌ์ดํด์ด ๋ฐ์ํ์ง ์์ผ๋ฉด
if (union(edge.from, edge.to)) {
minTotalWeight += edge.w;
edgesCount++;
}
if (edgesCount == N - 1)
break;
}
System.out.printf("%.2f\n",minTotalWeight);
// ๊ฑฐ๋ฆฌ๋ฅด ๊ตฌํ๊ธฐ ์ํด์ ์ ๊ณฑ์ ํ์ฉํด์ผ ํ๋ค.
private static double getDistance(Node n1, Node n2) {
double dx = n1.x - n2.x;
double dy = n1.y - n2.y;
return Math.sqrt(dx * dx + dy * dy);
}
private static int find(int a) {
if (parent[a] == a)
return a;
return parent[a] = find(parent[a]);
}
private static boolean union(int a, int b) {
int rootA = find(a);
int rootB = find(b);
// ์ด๋ฏธ ๊ฐ์ ์งํฉ์ด๋ฉด ํฉ์น์ง ์๋๋ค.
if (rootA == rootB)
return false;
// ์์ ๋ฒํธ์ ๋ฃจํธ๋ฅผ ๋ถ๋ชจ๋ก ์คํ
if (rootA < rootB) {
parent[rootB] = rootA;
} else {
parent[rootA] = rootB;
}
return true;
}
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
//๋
ธ๋์ ์ขํ๋ฅผ ๋ํ๋ด๋ ํด๋์ค
class Node {
long x, y;
public Node(long x, long y) {
this.x = x;
this.y = y;
}
}
//MST ์์ฑํด์ผ ํ๋ค.
//์๋ก์ ์งํฉ or prim ์๊ณ ๋ฆฌ์ฆ
class Edge implements Comparable<Edge> {
int from, to;
double w;
public Edge(int from, int to, double w) {
this.from = from;
this.to = to;
this.w = w;
}
@Override
public int compareTo(Edge o) {
// double ๋น๊ต ์ ์ค์ฐจ ๋ฌธ์ ๋๋ฌธ์ Math.signum()์ ์ฌ์ฉํ๋ ๊ฒ์ด ์์
return Double.compare(this.w, o.w);
}
}
public class backjoon_1774_๊ต๊ฐ {
static int[] parent;
public static void main(String[] args) throws IOException {
System.setIn(new FileInputStream("src/input.txt"));
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());
// 1. ์ด๊ธฐ ์ค์
parent = new int[N + 1];
// ๋ถ๋ชจ ๋ฐฐ์ด ์ด๊ธฐํ
for (int i = 1; i < N + 1; i++) {
parent[i] = i;
}
// 2. ์ขํ๊ฐ ์ ์ฅ
List<Node> spots = new ArrayList<>(N + 1);
spots.add(null);// 0๋ฒ์งธ๋ ๋น์ด๋๊ธฐ
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
long x = Long.parseLong(st.nextToken());
long y = Long.parseLong(st.nextToken());
spots.add(new Node(x, y));
}
// 3. ์ด๋ฏธ ์ฐ๊ฒฐ๋ M๊ฐ์ ํต๋ก ์ฒ๋ฆฌ (Union-Find๋ก ๋ฏธ๋ฆฌ ์งํฉ์ผ๋ก ๋ฌถ๊ธฐ)
// ์ด๋ฏธ ์ฐ๊ฒฐ๋ ๊ฐ์ ์ ๋ถ๋ชจ๋ฅผ ๊ฐ๊ฒ ํ๊ธฐ
int edgesCount = 0; // ์ ํ๋ ๊ฐ์ ์ ๊ฐ์
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int from = Integer.parseInt(st.nextToken());
int to = Integer.parseInt(st.nextToken());
if (union(from, to)) {
edgesCount++;
}
}
// 4. ๋ชจ๋ ๊ฐ๋ฅํ ๊ฐ์ ์ ๋ณด ์์ฑ
List<Edge> edges = new ArrayList<>();
// ๊ฐ์ ์ ๋ณด ์ ์ฅ
for (int i = 1; i <= N; i++) {
for (int j = i + 1; j <= N; j++) {
double weight = getDistance(spots.get(i), spots.get(j));
// Edge ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋ฆฌ์คํธ์ ์ถ๊ฐ
edges.add(new Edge(i, j, weight));
}
}
// 5. ๊ฐ์ ์ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌ
Collections.sort(edges);
// 6. ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ ์คํ
double minTotalWeight = 0; // ์๋ก ๋ง๋ค์ด์ผ ํ ํต๋ก์ ์ต์ ๊ธธ์ด ํฉ
for (Edge edge : edges) {
// ์ฌ์ดํด์ด ๋ฐ์ํ์ง ์์ผ๋ฉด
if (union(edge.from, edge.to)) {
minTotalWeight += edge.w;
edgesCount++;
}
if (edgesCount == N - 1)
break;
}
// 7. ๊ฒฐ๊ณผ ์ถ๋ ฅ
System.out.printf("%.2f\n",minTotalWeight);
}
// ๊ฑฐ๋ฆฌ๋ฅด ๊ตฌํ๊ธฐ ์ํด์ ์ ๊ณฑ์ ํ์ฉํด์ผ ํ๋ค.
private static double getDistance(Node n1, Node n2) {
double dx = n1.x - n2.x;
double dy = n1.y - n2.y;
return Math.sqrt(dx * dx + dy * dy);
}
private static boolean union(int a, int b) {
int rootA = find(a);
int rootB = find(b);
// ์ด๋ฏธ ๊ฐ์ ์งํฉ์ด๋ฉด ํฉ์น์ง ์๋๋ค.
if (rootA == rootB)
return false;
// ์์ ๋ฒํธ์ ๋ฃจํธ๋ฅผ ๋ถ๋ชจ๋ก ์คํ
if (rootA < rootB) {
parent[rootB] = rootA;
} else {
parent[rootA] = rootB;
}
return true;
}
private static int find(int a) {
if (parent[a] == a)
return a;
return parent[a] = find(parent[a]);
}
}