티스토리 뷰
문제 출처: https://www.acmicpc.net/problem/11780
11780번: 플로이드 2
첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가
www.acmicpc.net
플로이드 알고리즘으로 모든 쌍에 대해 최단거리를 구할 수 있다.
이 문제에서는 추가로 방문 경로를 구하여야 한다.
BFS같은 경우에서의 방문 경로는 prev 배열을 통해 a에서 b, b에서 c로 움직인 경우
prev[b] = a, prev[c] = b 으로 저장해두어
도착지에서 출발지까지 역순으로 찾을 수 있다.
플로이드에서는
1에서 3으로 가는 비용 10이고 prev배열은 prev[1][3] = 1으로 저장해둔다.
1에서 2를 경유하여 3으로 가는 비용이 5 이면 prev[1][3] = 2로 저장해둔다. (prev[1][2]는 1로 초기화 되어있다.)
prev[1][3] = 2
prev[1][2] = 1
위와 같이 방문 경로를 구할 수 있다.
1,2,3,4,5 에서 [1][3] 은 1-2-3이 최단거리이고 [3][5] 는 3-4-5가 최단거리 이고 [1][5]를 구할 때
[1][5] = [1][3] + [3][5] 일 것이고 prev는 [1][5] = 3으로 저장될 것이다.
이때 [3][5]에 있는 4가 생략되어 버리는 문제가 있다.
따라서 재귀함수를 만들어 prev[start][end] = middle에서
start~middle 부분의 경로와 middle~end 부분의 경로를 분할하여 리턴하도록 한다.
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<cstring>
#include<math.h>
#include<queue>
#include<vector>
using namespace std;
struct P{
int y, x;
};
const int INF = 12345678;
int N, M;
int arr[101][101];
int visit[101][101];
vector<int> pathFind(int start, int end) {
vector<int> path;
int middle = visit[start][end];
if (start == middle) {
path.push_back(end);
return path;
}
else {
vector<int> head = pathFind(start, middle);
vector<int> tail = pathFind(middle, end);
for (int i = 0; i < tail.size(); i++) {
head.push_back(tail[i]);
}
return head;
}
}
int main(void)
{
ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
fill(&arr[0][0], &arr[100][101], INF);
cin >> N >> M;
for (int i = 0; i < M; i++) {
int a, b, c;
cin >> a >> b >> c;
if (arr[a][b] != 0) {
if (arr[a][b] < c)continue;
}
arr[a][b] = c;
visit[a][b] = a;
}
for (int k = 1; k <= N; k++) {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (k == i || k == j || i == j)continue;
if (arr[i][k] + arr[k][j] < arr[i][j]) {
visit[i][j] = k;
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) {
cout << "0"<<" ";
}
else {
cout << arr[i][j] << " ";
}
}
cout << endl;
}
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (arr[i][j] == INF)cout << "0" << endl;
else {
vector<int> path = pathFind(i, j);
cout << path.size()+1 << " ";
cout << i << " ";
for (int z = 0; z < path.size(); z++) {
cout << path[z] << " ";
}
cout << endl;
}
}
}
}
'PS' 카테고리의 다른 글
| [백준] 14562번 태권왕 C++ (0) | 2022.07.28 |
|---|---|
| [백준] 11441번 합 구하기 C++ (0) | 2022.07.25 |
| [백준] 10775번 공항 C++ (0) | 2022.07.20 |
| [백준] 1759번 암호 만들기 C++ (0) | 2022.07.19 |
| [백준] 1182번 부분수열의 합 C++ (0) | 2022.07.18 |
- Total
- Today
- Yesterday
- 1738
- 후위 표기식
- 백준
- 스택
- 타임머신
- tea time
- 소셜네트워킹어플리케이션
- 어린왕자 C++
- 상범빌딩
- 골목길
- 1918
- 벨만포드
- 11657
- C++
- 1004
- 6018
- 7511
- 골목길C++
- 중위 표기식 후위 표기식으로 변환
- 6539
- 벨만-포드
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
