Codeforces 187B AlgoRace

問題

n個の町がn^2本の道でつながっている。
車がm個あり、それぞれの車で町iからjまで行くのにかかるコストが与えられる。


ここでr回のレースをする。
i回目のレースではsiからtiまで移動する。
この際、車をki回まで乗り換えてよい。
車は任意の町で、時間0で乗り換えられる。同じ車を何度使ってもよい。


それぞれのレースでの、ゴールまでの最短時間を求めよ。

制約条件

n≦60
m≦60
r≦10^5
k≦1000

方針

頂点がn個しかないので、車は最大でもn-1回しか乗り換える必要がない。
なので、dp[k][i][j]を頂点iから出発して頂点jに
k回乗り換えて移動するときの最短距離として、これを更新するDPをすればよい。


まずそれぞれの車での距離行列をワーシャルフロイドしておく。
dp[0][i][j]は、好きな車を使ってiからjへ行く最短距離。
dp[k+1][i][j] = {dp[k][i][l] + dp[0][l][j]}である。


これで計算量がO(n^3(k+m))になって間に合う。

ソースコード

int n, m, r, d[60][60][60], dp[60][60][60];
int ans[100000];
pair<pi, pi> q[100000];

int main(){
	scanf("%d%d%d", &n, &m, &r);
	rep(i, m){
		rep(j, n) rep(k, n) scanf("%d", d[i][j] + k);
		rep(k, n) rep(ii, n) rep(j, n) d[i][ii][j] = min(d[i][ii][j], d[i][ii][k] + d[i][k][j]);
	}
	rep(i, n) rep(j, n){
		rep(k, 60) dp[k][i][j] = inf;
		rep(k, m) dp[0][i][j] = min(dp[0][i][j], d[k][i][j]);
	}
	rep(i, 59) rep(j, n) rep(k, n) rep(l, n){
		dp[i+1][j][l] = min(dp[i+1][j][l], dp[i][j][k] + dp[0][k][l]);
	}
	
	rep(i, r){
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		printf("%d\n", dp[min(59, c)][a-1][b-1]);
	}
	
	return 0;
}