#문제
11404번: 플로이드
https://www.acmicpc.net/problem/11404
11404번: 플로이드
첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가
www.acmicpc.net
#접근방법
최단거리 알고리즘 중 모든정점에서 모든정점으로 가는 최단거리를 구하는 플로이드 워셜 알고리즘을 사용해야한다.
이 알고리즘은 O(n^3)이라는 시간복잡도가 걸린다.
#풀이
#include <stdio.h>
#define INF 987654321
int arr[105][105];
int main(){
int n,m;
int a,b,c;
scanf("%d",&n);
scanf("%d",&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
arr[i][j] = INF;
for(int i=1;i<=n;i++)
arr[i][i] = 0;
for(int i=0;i<m;i++){
scanf("%d %d %d",&a,&b,&c);
if(arr[a][b]>c)
arr[a][b] = c;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(arr[i][j]>arr[i][k]+arr[k][j])
arr[i][j] = arr[i][k]+arr[k][j];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
if(arr[i][j]==INF) printf("0 ");
else printf("%d ",arr[i][j]);
printf("\n");
}
return 0;
}
이 문제는 위에서 말한 것 처럼 플로이드 워셜 알고리즘을 사용하는게 적절하다. n<=100이므로 O(100^3)이라는 시간복잡도는 시간안에 돌아간다.
n,m을 입력받고 arr배열을 모두 무한대로 초기화해준다. 왜냐하면 최소거리를 구하는 조건문을 쓸 때 편리하기 때문이다. 그리고 arr[i][i]와 같이 자기자신은 0으로 초기화 해준다.
a,b,c를 m만큼 입력받을 때 같은 a,b값이 여러번 나올 수 있으므로 if(arr[a][b]>c)일 때 arr[a][b] = c를 입력받도록 조건문을 걸어준다.
배열을 다 입력받았으면 3중첩 반복문을 돌면서 arr[i][j] > arr[i][k] + arr[k][j]일 때 arr[i][j]의 값을 바꾸어준다. 이 반복문과 조건문이 플로이드 워셜 알고리즘의 핵심이다.
조건문에서 arr[i][j]의 의미는 i에서 j로 가는 비용이라는 뜻이다.
그리고 arr[i][k] + arr[k][j]의 의미는 i에서 k로 가는 비용과 k에서 j로가는 비용의 합이다. i에서 k를 거쳐서 j로 가는 비용이 원래 입력받았던 i에서 j로 가는 비용보다 작을 수 있으므로 이 때는 arr[i][j]값을 arr[i][k] + arr[k][j]로 바꿔준다.
그리고 arr배열을 출력하면되는데 이 때, 무한대로 초기화한 값을 0으로 출력을 하면 정답이다.
#성능
#정리
최단거리 알고리즘 중 모든정점에서 모든정점으로 가는 최단거리를 구하는 플로이드 워셜 알고리즘을 알고 있으면 쉽게 풀 수 있는 문제였다.
'하루 한 문제' 카테고리의 다른 글
[백준] 17144번 : 미세먼지 안녕! [C/C++] (0) | 2022.05.30 |
---|---|
[백준] 14938번 : 서강그라운드 [C/C++] (0) | 2022.05.27 |
[백준] 1967번 : 트리의 지름 [C/C++] (0) | 2022.04.10 |
[백준] 2638번 : 치즈 [C/C++] (2) | 2022.02.03 |
[백준] 1504번 : 특정한 최단 경로 [C/C++] (1) | 2022.01.30 |