https://www.acmicpc.net/problem/1058
1. 플로이드워셜로 푸는 방법
플로이드워셜은 N개의 노드에서 N개의 노드로 이동하는데 걸리는 최단 거리(비용)을 구할 수 있다. 즉, 각 노드에서 다른 N-1개의 노드로 몇 번의 이동으로 도달 가능한지 구한 후(=사람 a와 사람 b의 관계), 1번 또는 2번으로 이동이 가능하면 2-친구 관계이므로 카운트해주면 된다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
int n = Integer.parseInt(br.readLine());
int[][] map = new int[n][n];
for (int i = 0; i < n; i++) {
char[] arr = br.readLine().toCharArray();
for (int j = 0; j < n; j++) {
if (arr[j] == 'Y') {
map[i][j] = 1;
} else {
map[i][j] = Integer.MAX_VALUE;
}
}
}
// 플로이드워셜
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
if (map[i][k] != Integer.MAX_VALUE && map[k][j] != Integer.MAX_VALUE) {
map[i][j] = Math.min(map[i][j], map[i][k] + map[k][j]);
}
}
}
}
// 각 사람의 2-친구 수 구하기
int answer = 0;
for (int i = 0; i < n; i++) {
int friendCnt = 0;
for (int j = 0; j < n; j++) {
if (i == j) continue;
if (map[i][j] == 1 || map[i][j] == 2) {
friendCnt++;
}
}
answer = Math.max(answer, friendCnt);
}
System.out.println(answer);
}
}
플로이드워셜을 사용했을 때 시간 복잡도는 최대 O(N^3)이므로 50^3이다.
2. BFS로 푸는 방법
BFS를 사용하여 특정 노드로부터 최대 2까지 떨어진 노드 수를 구하면 된다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
int n = Integer.parseInt(br.readLine());
char[][] map = new char[n][n];
for (int i = 0; i < n; i++) {
map[i] = br.readLine().toCharArray();
}
int answer = 0;
// BFS
for (int i = 0; i < n; i++) {
boolean[] visited = new boolean[n];
Queue<Node> que = new LinkedList<>();
que.add(new Node(i, 0));
visited[i] = true;
int friendCnt = 0;
while (!que.isEmpty()) {
Node now = que.poll();
friendCnt++;
if (now.cnt < 2) {
for (int j = 0; j < n; j++) {
if (map[now.node][j] == 'Y' && !visited[j]) {
visited[j] = true;
que.add(new Node(j, now.cnt + 1));
}
}
}
}
answer = Math.max(answer, friendCnt - 1); // -1을 하는 이유 = 자기 자신을 poll 한 경우는 빼기
}
System.out.println(answer);
}
static class Node {
int node;
int cnt;
public Node(int node, int cnt) {
this.node = node;
this.cnt = cnt;
}
}
}
3. DFS로 푸는 방법
BFS로 푼 것처럼 DFS로도 풀 수 있다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static int n;
static char[][] map;
static boolean[] visited;
static Set<Integer> friends;
public static void main(String[] args) throws IOException {
n = Integer.parseInt(br.readLine());
map = new char[n][n];
for (int i = 0; i < n; i++) {
map[i] = br.readLine().toCharArray();
}
int answer = 0;
// DFS
for (int i = 0; i < n; i++) {
visited = new boolean[n];
friends = new HashSet<>();
visited[i] = true;
dfs(i, 0);
answer = Math.max(answer, friends.size() - 1); // set을 통해 2-친구 관계인 노드의 개수 계산
}
System.out.println(answer);
}
private static void dfs(int now, int cnt) {
friends.add(now);
if (cnt == 2) {
return;
}
for (int i = 0; i < n; i++) {
if (map[now][i] == 'Y' && !visited[i]) {
visited[i] = true;
dfs(i, cnt + 1);
visited[i] = false; // 방문 처리 초기화
}
}
}
}
이때 visited[i] = false 를 생략하면, 다음 상황에서 문제가 된다.
- 1번 노드에서 출발했을 때 1 → 2, 2 → 3을 지나가서 결과적으로 1, 2, 3을 방문 처리한다.
- 그리고 이어서 1 → 3을 지나려고 하는데 이미 3번 노드에 방문 처리가 되어있으므로 방문하지 않는다.
- 따라서 1번 노드와 4, 5번 노드는 2-친구 관계이지만 4, 5번 노드를 방문하지 않는다.
따라서 visited[i] = false 를 통해 방문 처리를 초기화해줬다.
그런데 이렇게 하면, 1번 노드의 2-친구 관계가 몇명인지 알 수 있는 방법이 없다. visited 배열을 순회하며 true인 노드들이 몇개인지 탐색하려고 했으나, visited 배열을 초기화하므로 해당 방법은 유효하지 않다.
따라서 set에 2-친구 관계인 노드들을 담아주었다. 만약 1 → 2 → 3을 탐색하여 1, 2, 3을 방문하고, 이어서 1 → 3 → 4을 탐색하면, 3번 노드는 중복으로 방문하게 된다. 따라서 방문할 때마다 카운트를 해주면 중복으로 방문한 것까지 카운트된다. 따라서 중복을 허용하지 않는 set을 사용했다.
'CS > Algorism' 카테고리의 다른 글
[프로그래머스] 등대 (1) | 2024.10.18 |
---|---|
다익스트라 알고리즘 - 우선순위 큐와 방문 처리에 대해 (0) | 2024.09.21 |
[백준] 10713. 기차 여행 (0) | 2024.07.05 |
[백준] 1941. 소문난 칠공주 (0) | 2024.07.03 |
[백준] 7570. 줄 세우기 (0) | 2024.07.01 |