ARC035 C - アットコーダー王国の交通事情
解法
頂点数が小さいので,ワーシャルフロイドでよい.
ただし,建設するたびにワーシャルフロイドすると間に合わない.
よく考えると,x-y 間に橋を作ったときに最短経路が変わるのは,x-yを経由するという意味にほかならない.
すると,最短経路を更新するときは
d[i][j] = min(d[i][j], d[i][x] + d[x][y] + d[y][j])
のように,i -> x -> y -> j という経路だけ確認すれば良いことになる.
もちろん,i -> y -> x -> j の経路も確認する.
これは O(N^2) でできるので,クエリに対して O(KN^2) で求まる.
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; constexpr int INF = 1e9; int main() { int N, M; cin >> N >> M; vector<vector<int>> d(N, vector<int>(N, INF)); for(int i = 0; i < N; ++i) { d[i][i] = 0; } for(int i = 0; i < M; ++i) { int a, b, c; cin >> a >> b >> c; a--; b--; d[a][b] = min(d[a][b], c); d[b][a] = d[a][b]; } for(int k = 0; k < N; ++k) { for(int i = 0; i < N; ++i) { for(int j = 0; j < N; ++j) { d[i][j] = min(d[i][j], d[i][k] + d[k][j]); } } } int K; cin >> K; while(K--) { int x, y, z; cin >> x >> y >> z; x--; y--; if(d[x][y] > z) { d[x][y] = d[y][x] = z; for(int i = 0; i < N; ++i) { for(int j = i + 1; j < N; ++j) { int t = d[i][x] + d[x][y] + d[y][j]; t = min(t, d[i][y] + d[y][x] + d[x][j]); d[i][j] = d[j][i] = min(d[i][j], t); } } } ll sum = 0; for(int i = 0; i < N; ++i) { for(int j = i + 1; j < N; ++j) { sum += d[i][j]; } } cout << sum << endl; } }
感想
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0526
これと一緒.AOJのほうは制約がちょっと違うからゴリ押せるんだけど.