11780번 - 플로이드 2
11404 플로이드 문제에서 경로를 구하는 문제가 추가되었다.
플로이드 워셜에서 경로를 구할 때는, D[i][j] 값이 갱신 될때, 2차원 via 배열에 k값을 넣는 것이다.
그렇게 된다면 i 에서 j 를 갈때 꼭 k를 거쳐가야 한다는 뜻이 되기 때문에,
이는 i 에서 k 까지, k에서 j 까지의 경로를 구해서 합치면 되기 때문이다.
그래서 makePath 함수에서 이를 재귀를 통해서 구하도록 하였다.
주의할 점은 via 함수를 처음에 -1로 초기화를 시켜줘야 한다는 점이다.
그리고 makePath 에서 중복되는 값들을 처리하기 위해 pop을 한번 시킨다는 것도 주의해야 한다.
마지막으로 출력할 때, 만약 path 에 1개의 값만 들어있다면, 이는 다른 곳으로 갈 수 없다는 뜻이 되므로 0을 출력하면 된다.
<정답 코드>
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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #include<iostream> #include<vector> using namespace std; const int INF = 20000000; int D[101][101]; int via[101][101]; vector<int> makePath(int s,int e, vector<int> path) { if (via[s][e] == -1) { path.push_back(s); if (s != e) { path.push_back(e); } return path; } else { path = makePath(s, via[s][e], path); path.pop_back(); path = makePath(via[s][e], e, path); } return path; } int main() { //freopen("input.txt", "r", stdin); int n, m; scanf("%d %d", &n, &m); for (int i = 0; i < 101; i++) { for (int j = 0; j < 101; j++) { D[i][j] = i == j ? 0 : INF; via[i][j] = -1; } } for(int i=0;i<m;i++) { int a, b, c; scanf("%d %d %d", &a, &b, &c); D[a][b] = D[a][b] > c ? c : D[a][b]; } for (int k = 1; k <= n; k++) { for (int i = 1; i <=n; i++) { for (int j = 1; j <=n; j++) { if (D[i][j] > D[i][k] + D[k][j]) { D[i][j] = D[i][k] + D[k][j]; via[i][j] = k; } } } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (D[i][j] >= INF) { printf("0 "); } else { printf("%d ", D[i][j]); } } puts(""); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { vector<int> path; path = makePath(i, j, path); if (path.size() == 1) { printf("0\n"); } else { printf("%d ", path.size()); for (int k = 0; k < path.size(); k++) { printf("%d ", path[k]); } puts(""); } } } return 0; } | cs |
반응형