https://www.acmicpc.net/problem/13141
13141번: Ignition
첫 번째 줄에는 그래프의 정점의 수 N과 간선의 수 M이 주어진다. (2 ≤ N ≤ 200, N-1 ≤ M ≤ 20,000) 두 번째 줄부터 M개의 줄에는 각 간선의 시작점 S, 끝점 E, 길이 L이 주어진다. (1 ≤ L ≤ 100) 시작점
www.acmicpc.net
[ 문제풀이 ]
이 문제를 풀기 전에 다음 글을 먼저 읽어보시는 것을 추천드립니다!
https://rudalsd.tistory.com/24?category=1064608
[ 알고리즘 ] 플로이드 와샬 알고리즘(Floyd Warshall Algorithm)
오늘 설명할 알고리즘은 플로이드 와샬 알고리즘(Floyd Warshall Algorithm)입니다. 이 알고리즘은 dijkstra와 비슷하게 각 정점까지 가는 최단 거리를 알아낼 수 있습니다. 플로이드 와샬 알고리즘이
rudalsd.tistory.com
1. 각 노드에서 노드까지 최장거리를 저장해줍니다.
2. 플로이드 와샬 알고리즘을 이용하여 각 노드에서 노드까지의 최단거리를 구합니다.
3. 모든 노드를 체크하면서 각 노드에서 출발했을 때 가장 오래 걸리는 시간을 저장합니다.
4. 가장 오래 걸리는 시간들 중 가장 빠른 시간을 출력합니다.
위의 3번 과정에서 가장 오래 걸리는 시간을 구하는 방법은 다음과 같습니다.
만약 i번 노드와 j번 노드 사이의 간선들이 모두 타는 데 걸리는 시간은 두 노드 사이의 가장 긴 간선이 타는 데 걸리는 시간입니다. 따라서 노드 i와 노드 j에 모두 불이 붙은 시점에서 둘 사이에 남아 있는 노드의 길이를 구해 시간을 구해주면 됩니다.
먼저 시작 노드를 i라고 하고 구하고자 하는 두 노드를 각각 j, k라고 하면, 두 노드에 모두 불이 붙었을 때 남아 있는 간선의 길이는 다음과 같습니다.
remain = longest[ j ][ k ] - (dist[ i ][ j ] - dist[ i ][ k ])
불이 j노드에 도착 했을 때 남아있는 시간이 remain이므로
time = dist[ i ][ j ] + remain / 2
가 됩니다.
이때 remain이 0보다 작다면 모든 간선이 다 탄 상태이므로 time을 구할 필요가 없어집니다.
따라서, remain > 0인 상태에서만 값을 구해주면 됩니다.
마지막으로 구해진 time들 중 가장 짧은 time을 ans에 넣어주시면 됩니다.
[ 소스 코드 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #include<iostream> using namespace std; int N, M; int arr[201][201]; int longest[201][201]; float ans = 987654321; int main() { scanf("%d %d", &N, &M); for (int i = 1; i <= N; i++) { //각 노드까지 거리 초기화 for (int j = 1; j <= N; j++) { if (i == j) { arr[i][j] = 0; } else { arr[i][j] = 987654321; } } } for (int i = 0; i < M; i++) { int S, E, L; scanf("%d %d %d", &S, &E, &L); if (arr[S][E] > L) { //최단거리 저장 arr[S][E] = L; arr[E][S] = L; } if (longest[S][E] < L) { //최장거리 저장 longest[S][E] = L; longest[E][S] = L; } } for (int i = 1; i <= N; i++) { //각각의 노드에서 노드까지 최단거리 갱신 for (int j = 1; j <= N; j++) { for (int k = 1; k <= N; k++) { if (arr[j][k] > arr[j][i] + arr[i][k]) { arr[j][k] = arr[j][i] + arr[i][k]; } } } } for (int i = 1; i <= N; i++) { //i번 노드에서 시작했을 때 다 타는데 걸리는 시간 time float time = 0; for (int j = 1; j <= N; j++) { for (int k = 1; k <= N; k++) { float remain = longest[j][k] - (arr[i][j] - arr[i][k]); if (remain > 0) { time = max(time, arr[i][j] + remain / 2); } } } ans = min(time, ans); //time 중 가장 짧은 시간 저장 } printf("%.1f", ans); } | cs |
'백준' 카테고리의 다른 글
[ 백준 ] 17401번 - 일하는 세포 (C++) (0) | 2022.08.10 |
---|---|
[ 백준 ] 14942번 - 개미 (C++) (0) | 2022.08.09 |
[ 백준 ] 7578번 - 공장 (C++) (0) | 2022.08.07 |
[ 백준 ] 16287번 - Parcel (C++) (0) | 2022.08.06 |
[ 백준 ] 10026번 - 적록색약 (C++) (0) | 2022.08.05 |