문제
컴공 출신은 치킨집을 하게 되어있다. 현실을 부정하지 말고 받아들이면 마음이 편하다. 결국 호석이도 2050년에는 치킨집을 하고 있다. 치킨집 이름은 "호석이 두마리 치킨"이다.
이번에 키친 도시로 분점을 확보하게 된 호석이 두마리 치킨은 도시 안에 2개의 매장을 지으려고 한다. 도시는 N 개의 건물과 M 개의 도로로 이루어져 있다. 건물은 1번부터 N번의 번호를 가지고 있다. i 번째 도로는 서로 다른 두 건물 Ai 번과 Bi 번 사이를 1 시간에 양방향으로 이동할 수 있는 도로이다.
키친 도시에서 2개의 건물을 골라서 치킨집을 열려고 한다. 이 때 아무 곳이나 열 순 없어서 모든 건물에서의 접근성의 합을 최소화하려고 한다. 건물 X 의 접근성은 X 에서 가장 가까운 호석이 두마리 치킨집까지 왕복하는 최단 시간이다. 즉, "모든 건물에서 가장 가까운 치킨집까지 왕복하는 최단 시간의 총합"을 최소화할 수 있는 건물 2개를 골라서 치킨집을 열려고 하는 것이다.
컴공을 졸업한 지 30년이 넘어가는 호석이는 이제 코딩으로 이 문제를 해결할 줄 모른다. 알고리즘 퇴물 호석이를 위해서 최적의 위치가 될 수 있는 건물 2개의 번호와 그 때의 "모든 건물에서 가장 가까운 치킨집까지 왕복하는 최단 시간의 총합"을 출력하자. 만약 이러한 건물 조합이 여러 개라면, 건물 번호 중 작은 게 더 작을수록, 작은 번호가 같다면 큰 번호가 더 작을수록 좋은 건물 조합이다.
입력
첫 번째 줄에 건물의 개수 N과 도로의 개수 M 이 주어진다. 이어서 M 개의 줄에 걸쳐서 도로의 정보 Ai , Bi 가 공백으로 나뉘어서 주어진다. 같은 도로가 중복되어 주어지는 경우는 없다. 어떤 두 건물을 잡아도 도로를 따라서 오고 가는 방법이 존재함이 보장된다.
출력
한 줄에 건물 2개가 지어질 건물 번호를 오름차순으로 출력하고, 그때 모든 도시에서의 왕복 시간의 합을 출력한다.
만약 건물 조합이 다양하게 가능하면, 작은 번호가 더 작은 것을, 작은 번호가 같다면 큰 번호가 더 작은 걸 출력한다.
제한
- 2 ≤ N ≤ 100
- N-1 ≤ M ≤ N×(N - 1)/2
- 1 ≤ Ai , Bi ≤ N (Ai ≠ Bi)
예제 입력 1 복사
5 4
1 3
4 2
2 5
3 2
예제 출력 1 복사
1 2 6
위의 그림과 같이 1번과 2번 건물에 치킨집을 짓게 되면 1번부터 5번 건물에 대해 치킨집까지의 왕복 시간이 0, 0, 2, 2, 2 로 최소가 된다. 2번과 3번 건물에 지어도 동일한 왕복 시간이 나오지만 더 작은 건물 번호를 출력해야 함을 유의하자.
간단한 플로이드 워셜 알고리즘이었다. 하지만 두 개의 치킨집을 임의로 선정해서 모든 노드와의 최단 거리를 계산하는 부분이 조금 떠올리기 어려워서 답지를 참고한 문제이다.
+ 플로이드 워셜 알고리즘 참고 youtube (동빈나)
https://www.youtube.com/watch?v=9574GHxCbKc
문제의 로직
1. n,m 입력을 받아준다.
2. 플로이드 워셜 그래프를 초기화 시켜준다.(0,0이나 1,1 같이 같은 숫자의 그래프는 0으로 초기화, 그 외에는 INF)
3. 입력을 받아 graph의 간선을 양방향으로 연결시켜준다.
4. 플로이드 워셜 알고리즘을 한번 돌려줘서 최단거리를 갱신 시켜준다.
5. 임의의 두 점을 이중 for문을 통하여 생성하고 그 두 점에서 모든 건물까지의 거리를 두 점에서의 거리 중 더 작은 걸로 모두 합쳐준다.
6. 모든 경우의 수의 두 점에서의 거리 중 가장 작은 값은 결국 정답이 된다.
7. 두 점과 왕복 거리를 출력한다. 이때 왕복거리는 *2를 해주면 된다.
- java 풀이
import java.io.*;
import java.sql.Array;
import java.util.*;
import java.util.stream.Collectors;
public class Main {
private static int INF = 101;
private static int[][] graph = new int[101][101];
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Scanner sc = new Scanner(System.in);
int n, m;
n = sc.nextInt();
m = sc.nextInt();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
graph[i][j] = INF;
if (i == j) {
graph[i][j] = 0;
}
}
}
for (int i = 0; i < m; i++) {
int a, b;
a = sc.nextInt();
b = sc.nextInt();
graph[a][b] = 1;
graph[b][a] = 1;
}
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (graph[i][j] > graph[i][k] + graph[k][j]) {
graph[i][j] = graph[i][k] + graph[k][j];
}
}
}
}
int min = Integer.MAX_VALUE;
int p1=0;
int p2=0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if(i==j) continue;
int now = sum(i,j,n);
if(min > now){
p1= i;
p2 = j;
min = now ;
}
}
}
System.out.println(p1+" "+p2+" "+min*2);
}
public static int sum(int p1, int p2, int n) {
int sum =0;
for(int i = 1 ; i <= n ; i ++){
if(i==p1||i==p2)continue;
sum += Math.min(graph[p1][i],graph[p2][i]);
}
return sum;
}
}
'Algorythms' 카테고리의 다른 글
백준 2458번 키 순서 java 풀이 (0) | 2023.11.21 |
---|---|
백준 11404번 플로이드 java 풀이 (1) | 2023.11.20 |
백준 11908번 카드 java 풀이 (0) | 2023.11.17 |
백준 11265번 끝나지 않는 파티 java 풀이 (1) | 2023.10.19 |
백준 23303번 java 풀이 (0) | 2023.10.14 |