Particle

競技プログラミングについての雑記

SRM 652 Div1 Medium MaliciousPath

K = 0 のときは、 dijkstra で解ける。
頂点を *1 と拡張すると、K>0 の場合も dijkstra を多少書き換えるだけで解くことができる。
辺の長さが少し特殊なので、k=0..K として順番に dijkstra を行うことで効率よく最短路が求まる。
計算量は、O(K(N+M)logN)となる。

下記コードは editorial や他人の解説記事を読んだ感じではおそらく正しいが、practice ルームでは TLE となるので注意。(同じような現象が最近 (2018/02/07) よく起こるので、サーバ側の問題だと思う)

#define NN 1010
vector<P> g[NN], g2[NN];
ll d[NN][NN], d2[NN][NN];

class MaliciousPath {
	public:
	long long minPath(int n, int K, vector <int> f, vector <int> t, vector <int> c) {
		rep(i, n) g[i].clear();
		rep(i, n) g2[i].clear();
		int m = f.size();
		rep(i, m){
			g[f[i]].pb(P(c[i], t[i]));
			g2[t[i]].pb(P(c[i], f[i]));
		}
		rep(i, n){
			sort(all(g[i]));
			sort(all(g2[i]));
		}
		rep(i, n) fill(d[i], d[i]+NN, INF);
		mset(d2, 0);
		rep(k, K+1) d[n-1][k] = 0;
		rep(k, K+1){
			priority_queue<P, vector<P>, greater<P>> q;
			q.push(P(0, n-1));
			while(!q.empty()){
				P p = q.top(); q.pop();
				ll l = p.fst, u = p.snd;
				if(d[u][k]<l) continue;
				for(auto x: g2[u]){
					ll l2 = max(d2[x.snd][k], l+x.fst), v = x.snd;
					if(d[v][k]>l2){
						d[v][k] = l2;
						q.push(P(l2, v));
					}
				}
			}
			rep(i, m) chmax(d2[f[i]][k+1], d[t[i]][k]+c[i]);
		}
		return d[0][K]==INF?-1:d[0][K];
	}
};

*1:頂点), (token数