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 C# (judge verdict: Accepted)

using System;
using System.Linq;
using System.Collections.Generic;

public class Hello{
    public static Station[] Stations;
    public static int[][][] Rails;
    
    public static void Main(){
        Stations = new Station[Consts.MAXSTATIONS + 1];
        for(int i = 0; i < Stations.Length; i++){
            Stations[i] = new Station();
        }
        Stations[0].Checked = true;
        
        Rails = new int[Consts.MAXSTATIONS + 1][][];
        for(int i = 0; i < Rails.Length; i++){
            Rails[i] = new int[Consts.MAXSTATIONS + 1][];
            for(int j = 0; j < Consts.MAXSTATIONS + 1; j++){
                Rails[i][j] = Enumerable.Repeat(-1, 2).ToArray();
            }
        }
        while(true){
            // init
            for(int i = 0; i < Rails.Length; i++)
                for(int j = 0; j < Rails[i].Length; j++)
                    for(int k = 0; k < Rails[i][j].Length; k++)
                        Rails[i][j][k] = -1;
                        
            // init data input
            string[] InputMapData = Console.ReadLine().Split(' ');
            int RailNum = int.Parse(InputMapData[0]);
            int StationNum = int.Parse(InputMapData[1]);
            if(RailNum == 0 && StationNum == 0) break;

            // rails data input
            for(int i = 0; i < RailNum; i++){
                string[] InputRailData = Console.ReadLine().Split(' ');
                int FromStationID = int.Parse(InputRailData[0]);
                int ToStationID = int.Parse(InputRailData[1]);
                int Cost = int.Parse(InputRailData[2]);
                int Time = int.Parse(InputRailData[3]);
                Rails[FromStationID][ToStationID][0] = Cost;
                Rails[FromStationID][ToStationID][1] = Time;
                Rails[ToStationID][FromStationID][0] = Cost;
                Rails[ToStationID][FromStationID][1] = Time;
            }
            // querys
            int QueryNum = int.Parse(Console.ReadLine());
            for(int i = 0; i < QueryNum; i++){
                string[] InputQuery = Console.ReadLine().Split(' ');
                Console.WriteLine(
                    Solve(
                        int.Parse(InputQuery[0]),
                        int.Parse(InputQuery[1]),
                        int.Parse(InputQuery[2])
                    )
                );
            }
        }
    }
    
    public static int Solve(int StartStationID, int GoalStationID, int QueryType){
        // initial data
        int CheckStationID = 0;
        for(int i = 1; i < Stations.Length; i++){
            Stations[i].MinCost = int.MaxValue;
            Stations[i].Checked = false;
        }
        Stations[StartStationID].MinCost = 0;
        PQueue pq = new PQueue();
        pq.Enqueue(StartStationID, Stations[StartStationID].MinCost);

        int TmpTotalCost;
        while(true){
            CheckStationID = pq.Dequeue();
            if(Stations[CheckStationID].Checked) continue;
            Stations[CheckStationID].Checked = true;
            if(CheckStationID == GoalStationID) break;
            for(int ToStationID = 1; ToStationID < Stations.Length; ToStationID++){
                if(Rails[CheckStationID][ToStationID][QueryType] < 0) continue;
                TmpTotalCost = Stations[CheckStationID].MinCost + Rails[CheckStationID][ToStationID][QueryType];
                if(TmpTotalCost < Stations[ToStationID].MinCost){
                    Stations[ToStationID].MinCost = TmpTotalCost;
                    pq.Enqueue(ToStationID, Stations[ToStationID].MinCost);
                }
                
            }
        }
        return Stations[GoalStationID].MinCost;
    }
}

public class Station{
    public int MinCost {get;set;}
    public bool Checked {get;set;}
    public Station(){
        MinCost = int.MaxValue;
        Checked = false;
    }
}

public static class Consts{
    public static int MAXSTATIONS = 100;
}

public class PQueue{
    private List<int[]> Tree;
    public PQueue(){
        Tree = new List<int[]>();
    }
    public void Enqueue(int key, int value){
        int nIdx = Tree.Count;
        Tree.Add(new int[]{key, value});
        if(1 < Tree.Count){
            while(nIdx != 0){
                int ParentIdx = (nIdx - 1) / 2;
                if(Tree[ParentIdx][1] > Tree[nIdx][1]){
                    int[] tmp = Tree[ParentIdx]; Tree[ParentIdx] = Tree[nIdx]; Tree[nIdx] = tmp;
                    nIdx = ParentIdx;
                }
                else break;
            }
        }
    }
    public int Dequeue(){
        int Ret = 0;
        try{
            Ret = Tree[0][0];
            Tree[0] = Tree[Tree.Count - 1];
            Tree.RemoveAt(Tree.Count - 1);
        }
        catch(Exception e){
            throw e;
        }
        int nIdx = 0;
        while(true){
            int LChildIdx = nIdx * 2 + 1;
            int RChildIdx = LChildIdx + 1;
            int TargetIdx = 0;
            if(RChildIdx < Tree.Count){
                TargetIdx = Tree[LChildIdx][1] > Tree[RChildIdx][1] ?
                            RChildIdx :
                            LChildIdx ;
            }
            else if(LChildIdx < Tree.Count)
                TargetIdx = LChildIdx;
            else break;
            if(Tree[nIdx][1] > Tree[TargetIdx][1]){
                int[] tmp = Tree[TargetIdx]; Tree[TargetIdx] = Tree[nIdx]; Tree[nIdx] = tmp;
            }
            nIdx = TargetIdx;
        }
        return Ret;
    }
    public void Print(string Sepalator){
        for(int i = 0; i < Tree.Count; i++){
            System.Console.Write(Tree[i][0] + "," + Tree[i][1]);
            if(i != Tree.Count - 1) System.Console.Write(Sepalator);
        }
        System.Console.WriteLine();
    }
}