문제 출처 :
https://www.acmicpc.net/problem/1719
플로이드-와샬 알고리즘으로 풀면 되는 문제.업데이트될 때마다, 지나온 루트도 업데이트해주고, 마지막에 프린트할 때에만 루트의 1번째 값 출력해주면 된다.(0번째는 시작점, 마지막은 종착점)
이 때 주의할 점은 저 경로들이 양방향이라는 점이다.
#include <iostream>
#include <vector>
#define INF 9876543210
using namespace std;
int n, m;
long long dp[201][201];
vector<int> v[201][201];
long long Min(long long a, long long b) { return a < b ? a : b; }
void input() {
cin >> n >> m;
// init
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
dp[i][j] = INF;
if (i == j)
dp[i][j] = 0;
// 자기 자신으로의 루트는 cost 0
v[i][j].push_back(i);
v[i][j].push_back(j);
}
}
for (int i = 1; i <= m; i++) {
int a, b, cost;
cin >> a >> b >> cost;
dp[a][b] = Min(cost, dp[a][b]);
dp[b][a] = Min(cost, dp[b][a]);
}
}
void floyd_Warshall() {
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (dp[i][j] > dp[i][k] + dp[k][j]) {
dp[i][j] = dp[i][k] + dp[k][j];
vector<int> tmp = v[k][j];
v[i][j].clear();
v[i][j] = v[i][k];
for(int l = 1; l < tmp.size(); l++){
v[i][j].push_back(tmp[l]);
}
}
}
}
}
}
void print_() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == j)
cout << "- ";
else{
cout << v[i][j][1] << " ";
}
}
cout << "\n";
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
input();
floyd_Warshall();
print_();
return 0;
}
