Problem:
鉄道路線

ある国の鉄道網に、自動改札を導入することになりました。導入にあたって難しい問題の一つは、与えられた切符で、指定された駅の間を移動できるかどうかを判定することです。それぞれの切符には乗車駅と降車駅が記載されています。この切符でできるのは、「乗車駅で乗って、降車駅で降りる」ことだけではなく、途中乗車や途中下車も許されています。

この鉄道網にはS 個の駅があり、そのうちR 組の駅は隣り合っていて、他の駅を経由せずに双方向に鉄道で移動することができます。隣り合った駅を結ぶ線路はひとつしかありません。隣り合った駅の間の距離は、この線路に沿って測った距離です。ある駅からある駅までの経路は鉄道網の形状によっては複数通り考えられますが、そのうち最も距離が短くなるような経路を最短経路と呼ぶことにします。そのような経路が複数ある場合、どちらも最短経路として認められます。

乗車駅 a、降車駅 b の切符で駅 c から駅 d まで移動できるのは、以下の条件をすべて満たす経路 p が存在するときです。

経路 p は、駅 a から駅 b への最短経路である。

経路 p は、駅 a から出発し、駅 c、駅 d の順に経由し、駅 b で終わる経路である。また、駅 c から駅 d の区間はこの2 駅の最短経路になっている。

路線図と切符の情報が与えられます。次に、始点と終点の組がいくつか与えられるので、その切符で始点から終点へ移動できるかどうかを判定するプログラムを作成してください。

入力

入力は１つのデータセットからなる。入力データは以下の形式で与えられる。

S R
u1 v1 w1
u2 v2 w2
:
uR vR wR
a b Q
c1 d1
:
cQ dQ

各行で与えられる数値は１つの空白で区切られている。

１行目は２つの整数からなる。S (2 ≤ S ≤ 100000) は鉄道路線図に現れる駅の数、R (1 ≤ R ≤ 200000) は隣り合った駅の組の数である。続く R 行に、隣り合った駅の間を直接つなぐ線路の情報が与えられる。ui と vi (1 ≤ ui, vi ≤ S) は i 番目の線路の両端の駅の番号を示す。wi (1 ≤ wi ≤ 1000) はこれらの駅の間の距離を表す整数である。ただし、各駅には 1 から S までの番号が重複なく割り振られており、ui ≠ vi とする。

続く１行は３つの整数からなる。最初の２つの整数は切符の区間を表し、a は乗車駅、b は降車駅 (1 ≤ a, b ≤ S) である。３つ目の整数 Q (1 ≤ Q ≤ 40000) は質問の数を示す。続く Q 行に質問が与えられる。 ci とdi (1 ≤ ci, di ≤ S)は i 番目の質問の乗車駅と降車駅を示す。ただし、a ≠ b、ci ≠ di とする。

出力

質問ごとに、与えられた切符で移動できるなら Yes を、できないなら No を１行に出力する。

入力例

6 7
1 2 3
1 4 1
2 3 5
4 3 1
3 6 2
4 5 2
5 6 1
1 6 6
1 6
4 3
4 6
5 6
2 6
2 5

出力例

Yes
Yes
Yes
Yes
No
No

Solution in C++ (judge verdict: Accepted)

#include <queue>
#include <cstdio>
#include <cstring>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

typedef long long ll;

const int INF=1<<29;

struct edge{ int v,cost; };

void Dijkstra(int n,const vector<edge> *G,int s,int *dist){
	rep(u,n) dist[u]=(u==s?0:INF);
	priority_queue< pair<int,int> > Q; Q.push(make_pair(0,s));
	while(!Q.empty()){
		int d_now=-Q.top().first,u=Q.top().second; Q.pop();
		if(d_now>dist[u]) continue;
		rep(i,G[u].size()){
			int v=G[u][i].v,cost=G[u][i].cost;
			if(dist[v]>dist[u]+cost){
				dist[v]=dist[u]+cost;
				Q.push(make_pair(-dist[v],v));
			}
		}
	}
}

int main(){
	int n,m; scanf("%d%d",&n,&m);
	static vector<edge> G[100000];
	rep(i,m){
		int u,v,cost; scanf("%d%d%d",&u,&v,&cost); u--; v--;
		G[u].push_back((edge){v,cost});
		G[v].push_back((edge){u,cost});
	}

	int a,b,q; scanf("%d%d%d",&a,&b,&q); a--; b--;
	static int c[40000],d[40000];
	rep(i,q) scanf("%d%d",c+i,d+i), c[i]--, d[i]--;

	// calculate distances from a/b
	static int dist_a[100000]; Dijkstra(n,G,a,dist_a);
	static int dist_b[100000]; Dijkstra(n,G,b,dist_b);

	// build the shortest path DAG from a to b
	static vector<int> H[100000];
	rep(u,n) rep(i,G[u].size()) {
		int v=G[u][i].v,cost=G[u][i].cost;
		if(dist_a[u]+cost+dist_b[v]==dist_a[b]) H[u].push_back(v);
	}

	// find a topological order of H
	vector<int> top;
	static int deg[100000]; // degree of vertices
	rep(u,n) rep(i,H[u].size()) {
		int v=H[u][i];
		deg[v]++;
	}
	queue<int> Q; Q.push(a);
	while(!Q.empty()){
		int u=Q.front(); Q.pop();
		top.push_back(u);
		rep(i,H[u].size()){
			int v=H[u][i];
			deg[v]--;
			if(deg[v]==0) Q.push(v);
		}
	}

	// query
	rep(i,(q+63)/64){
		static ll dp[100000];
		memset(dp,0,sizeof dp);
		rep(j,64) if(64*i+j<q) dp[c[64*i+j]]|=1LL<<j;
		rep(i,top.size()){
			int u=top[i];
			rep(j,H[u].size()){
				int v=H[u][j];
				dp[v]|=dp[u];
			}
		}
		rep(j,64) if(64*i+j<q) puts(dp[d[64*i+j]]&(1LL<<j)?"Yes":"No");
	}

	return 0;
}