본문 바로가기
ps

[백준] 11780 - 플로이드 2

by kariskan 2022. 8. 9.

https://www.acmicpc.net/problem/11780

 

11780번: 플로이드 2

첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가

www.acmicpc.net

 

문제 이름에 나와있는 것처럼 플로이드를 활용해서 푸는 문제인데, 출력이 굉장히 길다.

처음 출력은 플로이드를 수행한 결과 배열을 출력하는 것이고,

다음부터는 모든 정점 쌍 i, j에 대하여 i에서 j로 가는 경로중, 최단 경로일 때 거치는 정점을 출력하는 것이었다.

 

처음 출력은 플로이드-와샬 알고리즘을 이용해서 해결할 수 있다.

하지만 뒷부분의 출력 때문에 이 알고리즘 수행 중에, 경로를 저장하는 행위를 해야 하는데,

이 포스트에 나와있는 대로 따로 배열을 만들어 최단거리를 만드는 경로를 저장할 수 있다.

 

그럼 이 경로 배열을 통해 출력을 완성해야 한다.

정점 i에서 정점 j로 최단 거리를 통해 갈 때 거치는 모든 정점을 출력해야 하므로, 재귀 함수를 하나 만들었다.

 

만약 정점 1에서 정점 4로 갈 때 최단 경로가 1 -> 2 -> 3 -> 4라고 하자.

그렇다면 1에서 4로가는 최단경로는, 1에서 route[1][4]로가는 최단경로 + route[1][4]에서 4로가는 최단경로가 될 것이다.

 

그래서 아래와 같이 go 함수를 작성하였다.

이때 ans.pop_back()을 한 이유는 route[s][e]가 중복되기 때문이다.

 

#include <iostream>
#include <vector>
using namespace std;

int n, m;
int map[101][101];
int route[101][101];

void go(int s, int e, vector<int>& ans) {

	if (route[s][e] == 0) {
		ans.push_back(s);
		ans.push_back(e);
		return;
	}
    
	go(s, route[s][e], ans);
	ans.pop_back();
	go(route[s][e], e, ans);
}

int main() {
	cin >> n >> m;

	for (int i = 0; i < m; i++) {
		int a, b, c; cin >> a >> b >> c;
		if(map[a][b] == 0 || map[a][b] > c) map[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 (i == j)continue;
				if (map[i][k] && map[k][j]) {
					if (map[i][j] == 0 || map[i][j] > map[i][k] + map[k][j]) {
						map[i][j] = map[i][k] + map[k][j];
						route[i][j] = k;
					}
				}
			}
		}
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cout << map[i][j] << ' ';
		}
		cout << '\n';
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (i == j || !map[i][j])cout << "0 ";
			else {
            
				vector<int> ans;
				go(i, j, ans);
				cout << ans.size() << ' ';
                
				for (auto& k : ans) {
					cout << k << ' ';
				}
			}
			cout << '\n';
		}
	}

}

'ps' 카테고리의 다른 글

[백준] 5214 - 환승  (0) 2022.08.09
[백준] 1958 - LCS 3  (0) 2022.08.09
[백준] 2240 - 자두나무  (0) 2022.08.09
[백준] 2617 - 구슬 찾기  (0) 2022.08.09
[백준] 1719 - 택배  (0) 2022.08.09

댓글