문제
해설
백준 사이트 문제 탭의 단계별로 풀어보기 중 MST(최소 신장 트리)로 분류되어있는 문제로 섬에 번호를 부여한 뒤 섬과 섬(정점과 정점) 사이의 거리를 계산해 List에 저장 후 크루스칼 알고리즘을 적용해 풀이하였다. 만약 이 문제가 MST문제로 분류되어있지 않았다면 풀이 방법을 떠올릴 수 있었을까 ㅠㅠ?
풀이
import java.util.*;
import java.io.*;
public class Main {
static int N, M, num, answer, count;
static int[] parent;
static int[][] dir = { { 0, 1, }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
static int[][] board;
static Queue<Point> island;
static List<Edge> edgeList;
static boolean isRange(int i, int j) {
if (i >= 0 && i < N && j >= 0 && j < M)
return true;
return false;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
board = new int[N][M];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine(), " ");
for (int j = 0; j < M; j++) {
board[i][j] = Integer.parseInt(st.nextToken());
}
}
island = new LinkedList<>();
edgeList = new ArrayList<>();
num = 1;
division(); // 섬 번호 부여
connect();
parent = new int[num];
answer = 0;
count = 0;
mst();
System.out.println(count == num - 2 ? answer : -1);
}
static void mst() {
for (int i = 1; i < num; i++) {
parent[i] = i;
}
Collections.sort(edgeList);
for (int i = 0; i < edgeList.size(); i++) {
Edge e = edgeList.get(i);
int findA = find(e.st);
int findB = find(e.end);
if(findA != findB) {
parent[findB] = findA;
answer += e.cost;
count++;
}
}
}
static int find(int n) {
if(parent[n] == n) return n;
return find(parent[n]);
}
static void connect() {
while (!island.isEmpty()) {
Point p = island.poll();
for (int d = 0; d < 4; d++) {
Edge e = bridge(d, p.i, p.j, board[p.i][p.j]);
if(e != null) {
edgeList.add(e);
}
}
}
}
static Edge bridge(int d, int i, int j, int num) {
int ni = i, nj = j;
while (isRange(ni, nj)) {
ni += dir[d][0];
nj += dir[d][1];
if (!isRange(ni, nj) || board[ni][nj] == board[i][j]) {
break;
} else if (isRange(ni, nj) && board[ni][nj] > 0) {
int dist = (Math.abs(ni - i) + Math.abs(nj - j)) - 1;
if(dist <= 1) break;
return new Edge(num, board[ni][nj], dist);
}
}
return null;
}
static void division() {
boolean[][] visit = new boolean[N][M];
Queue<Point> queue = new LinkedList<>();
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (board[i][j] == 1 && !visit[i][j]) {
queue.add(new Point(i, j));
visit[i][j] = true;
board[i][j] = num;
while (!queue.isEmpty()) {
Point p = queue.poll();
island.add(p);
for (int d = 0; d < 4; d++) {
int ni = p.i + dir[d][0];
int nj = p.j + dir[d][1];
if (isRange(ni, nj) && board[ni][nj] == 1 && !visit[ni][nj]) {
visit[ni][nj] = true;
board[ni][nj] = num;
queue.add(new Point(ni, nj));
}
}
}
num++;
}
}
}
}
static void print() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
System.out.print(board[i][j] + "\t");
}
System.out.println();
}
System.out.println();
}
static class Edge implements Comparable<Edge>{
int st, end, cost;
public Edge(int st, int end, int cost) {
this.st = st;
this.end = end;
this.cost = cost;
}
@Override
public int compareTo(Edge o) {
return this.cost - o.cost;
}
}
static class Point {
int i, j;
public Point(int i, int j) {
this.i = i;
this.j = j;
}
}
}