95 C Volleyball

問題

n個の交差点がm本の双方向に通行可能な道路によって結ばれている。
m本の道路は、
始点s[i],終点t[i],距離w[i]の形式で与えられる。


各交差点にはタクシーがいて、利用料金は距離にかかわらずc[i]、ただし利用距離の限度はそれぞれt[i]である。


このとき、交差点xからyへ移動するのに必要な金額の最小値を求めよ。
移動が不可能である場合-1を出力せよ。

制約条件

n,m≦1000
wi≦10^9
ti,ci≦10^9

方針

まずは全点間の最短距離を求めたい。
が、ワーシャルフロイドをすると多分1000^3なのでTLE.
グラフが疎なのでDijkstra法を各頂点から行う。


全点間最短距離が求まったら、始点から料金でDijkstra法を行う。
(グラフは、距離がt[i]以下のときに移動できる、すなわち重みc[i]の枝があるとする)


以下のソースで二回目のDijkstra法はpriority_queueを使わない実装をしている。
(priority_queueを使うとO(E log V)で、使わないとO(V^2)。ここでは辺はV^2本なので、使わない実装のほうが高速なのでそっちにしてある。多分どっちでも通るけど)

ソースコード

int n,m; ll t[1000],c[1000];
ll d[1000][1000], cost[1000];
vector<vector<pi> >e;

void run(){
	cin>>n>>m;
	int x,y; cin>>x>>y; x--; y--;
	
	e.clear(); e.resize(n);
	rep(i,m){
		int s,t,c; cin>>s>>t>>c;
		s--; t--;
		e[s].pb(mp(t,c)); e[t].pb(mp(s,c));
	}
	rep(i,n)cin>>t[i]>>c[i];
	
	rep(i,n)rep(j,n)d[i][j]=1e12;
	rep(i,n){
		d[i][i]=0;
		priority_queue<pair<ll,int> >q;
		q.push(mp(0,i));
		while(!q.empty()){
			int c=q.top().second; ll cc=q.top().first;
			q.pop();
			if(d[i][c]<-cc)continue;
			
			rep(j,e[c].size())if(d[i][e[c][j].first]>-cc+e[c][j].second)
			q.push(mp(cc-e[c][j].second,e[c][j].first)),
			d[i][e[c][j].first]=-cc+e[c][j].second;
		}
	}

	bool v[1000]={};
	rep(i,n)cost[i]=1e12; cost[x]=0;
	rep(i,n){
		ll mn=1e12; int mni=-1;
		rep(j,n)if(!v[j]&&mn>cost[j])mni=j, mn=cost[j];
		if(mni==-1)break;
		v[mni]=1;
		
		rep(j,n)if(d[mni][j]<=t[mni]&&cost[j]>mn+c[mni])cost[j]=mn+c[mni];
	}
	cout<<(cost[y]==1e12?-1:cost[y])<<endl;
}