Problem:
青春の片道切符

太郎君は夏休みに電車で長旅をする計画を立てています。しかし高校生の身である太郎君が一ヵ月しかない夏休みで可能な限り遠くに旅をするには、出来るだけ安い行き方と出来るだけ早い行き方をそれぞれ見つけなければうまく計画が立てられません。太郎君が素敵な旅を満喫できるように、太郎君の計画の助けになるプログラムを作ってあげましょう。

線路の情報、駅の数を入力とし、問い合わせに応じて、最小金額または最短時間を出力するプログラムを作成してください。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロふたつの行で示されます。各データセットは以下の形式で与えられます。

n m
a1 b1 cost1 time1
a2 b2 cost2 time2
:
an bn costn timen
k
p1 q1 r1
p2 q2 r2
:
pk qk rk

1 行目に線路の情報の数 n (1 ≤ n ≤ 3000)と駅の数 m (1 ≤ m ≤ 100) が与えられます。

続く n 行に i 番目の路線の情報が与えられます。各路線の情報として、路線がつなぐ２つの駅の番号 ai, bi (1 ≤ ai, bi ≤ m)、料金 costi (1 ≤ costi ≤ 1000)、移動時間 timei (1 ≤ timei ≤ 1000) が与えられます。ただし、各駅は 1 から m まで順番に番号が付けられているものとします。
なお、ai と bi が線路でつながっていれば、ai から bi、 bi からai の両方の移動が同じ料金と時間で可能とします。

続く行に問い合わせの数 k (1 ≤ k ≤ 200) が与えられます。続く k 行に i 番目の問い合わせが与えられます。各問合わせとして、出発駅 pi 、到着駅 qi 、出力する値の種類 ri (0 または 1)が与えられます。なお、問い合わせには必ず経路があるものとします。

データセットの数は 50 を超えない。

Output

データセットごとに、最小金額もしくは最短時間を１行に出力します。ri が 0 の時は最小金額を、 1 の時は最短時間を出力します。

Sample Input

6 5
1 2 200 10
1 4 400 15
1 3 250 25
2 4 100 10
4 5 150 20
3 5 300 20
2
1 5 0
1 5 1
0 0

Output for the Sample Input

450
35

Solution in JAVA (judge verdict: Accepted)

import java.util.Arrays;
import java.util.Scanner;
public class Main
{
	public static void main(String[] args) 
	{
		Scanner in=new Scanner(System.in);
		int M=10000;
		for(;;)
		{
			int n=in.nextInt();//路線数
			int m=in.nextInt();//駅数
			if((n|m)==0)
				return;
			int cost[][]=new int[m+1][m+1];
			int time[][]=new int[m+1][m+1];
			for(int i=0;i<=m;i++)	{
				Arrays.fill(cost[i], M);
				Arrays.fill(time[i], M);}
			for(int i=0;i<=m;i++){
				cost[i][i]=0;
				time[i][i]=0;	}
			for(int i=0;i<n;i++)
			{
				int S=in.nextInt();
				int T=in.nextInt();
				int c=in.nextInt();
				int t=in.nextInt();
				cost[S][T]=c;
				cost[T][S]=c;
				time[S][T]=t;
				time[T][S]=t;
			}
			int nn=in.nextInt();
			for(int I=0;I<nn;I++)
			{
				int s=in.nextInt();
				int t=in.nextInt();
				int or=in.nextInt();
				if(or==0)
				{
					int p=0;
					int leng[]=new int[n+1];// minimum distance
					int v[] = new int[n+1];// decision flag
					for(int k=0;k<=m;k++)
					{
						leng[k]=M;
						v[k]=0;
					}
					leng[s]=0;
					for(int i=0;i<=m;i++)
					{
						int min=M;//最小の節点を探す
						for(int k=0;k<=m;k++)
						{
							if(v[k]==0&&leng[k]<min)
							{
								p=k;
								min=leng[k];
							}
						}
						v[p]=1;//確定フラグ
						for(int k=0;k<=m;k++) //pを経由してkに至長さがそれまでの最短経路より小さければ更新
						{
							if((leng[p]+cost[p][k])<leng[k])
								leng[k]=leng[p]+cost[p][k];
						}
					}
					System.out.println(leng[t]);
				}
				else
				{
					int p=0;
					int leng[]=new int[n+1];// minimum distance
					int v[] = new int[n+1];// decision flag
					for(int k=0;k<=m;k++)
					{
						leng[k]=M;
						v[k]=0;
					}
					leng[s]=0;
					for(int i=0;i<=m;i++)
					{
						int min=M;//最小の節点を探す
						for(int k=0;k<=m;k++)
						{
							if(v[k]==0&&leng[k]<min)
							{
								p=k;
								min=leng[k];
							}
						}
						v[p]=1;//確定フラグ
						for(int k=0;k<=m;k++) //pを経由してkに至長さがそれまでの最短経路より小さければ更新
						{
							if((leng[p]+time[p][k])<leng[k])
								leng[k]=leng[p]+time[p][k];
						}
					}
					System.out.println(leng[t]);
				}
			}
		}
	}
}