Problem:
青春の片道切符
太郎君は夏休みに電車で長旅をする計画を立てています。しかし高校生の身である太郎君が一ヵ月しかない夏休みで可能な限り遠くに旅をするには、出来るだけ安い行き方と出来るだけ早い行き方をそれぞれ見つけなければうまく計画が立てられません。太郎君が素敵な旅を満喫できるように、太郎君の計画の助けになるプログラムを作ってあげましょう。
線路の情報、駅の数を入力とし、問い合わせに応じて、最小金額または最短時間を出力するプログラムを作成してください。
Input
複数のデータセットの並びが入力として与えられます。入力の終わりはゼロふたつの行で示されます。各データセットは以下の形式で与えられます。
n
m
a
1
b
1
cost
1
time
1
a
2
b
2
cost
2
time
2
:
a
n
b
n
cost
n
time
n
k
p
1
q
1
r
1
p
2
q
2
r
2
:
p
k
q
k
r
k
1 行目に線路の情報の数
n
(1 ≤
n
≤ 3000)と駅の数
m
(1 ≤
m
≤ 100) が与えられます。
続く
n
行に
i
番目の路線の情報が与えられます。各路線の情報として、路線がつなぐ２つの駅の番号
a
i
,
b
i
(1 ≤
a
i
,
b
i
≤
m
)、料金
cost
i
(1 ≤
cost
i
≤ 1000)、移動時間
time
i
(1 ≤
time
i
≤ 1000) が与えられます。ただし、各駅は 1 から
m
まで順番に番号が付けられているものとします。
なお、
a
i
と
b
i
が線路でつながっていれば、
a
i
から
b
i
、
b
i
から
a
i
の両方の移動が同じ料金と時間で可能とします。
続く行に問い合わせの数
k
(1 ≤
k
≤ 200) が与えられます。続く
k
行に
i
番目の問い合わせが与えられます。各問合わせとして、出発駅
p
i
、到着駅
q
i
、出力する値の種類
r
i
(0 または 1)が与えられます。なお、問い合わせには必ず経路があるものとします。
データセットの数は 50 を超えない。
Output
データセットごとに、最小金額もしくは最短時間を１行に出力します。
r
i
が 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

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Pint = pair<int, int>;
using Tuple = tuple<int, int, int>;
using Graph = vector<vector<Tuple>> ;

int main() {
    int n, m;
    while (1) {
        cin >> n >> m;
        if (m == 0) break;
        Graph g(m);
        for (int a, b, cost, time; n; n--) {
            cin >> a >> b >> cost >> time;
            a--; b--;
            g[a].push_back(Tuple(cost, time, b));
            g[b].push_back(Tuple(cost, time, a));
        }
        vector<vector<vector<int>>> dist(2, vector<vector<int>>(m, vector<int>(m, -1)));
        priority_queue<Pint, vector<Pint>, greater<Pint>> pq;
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < m; j++) {
                pq.push({ 0, j });
                dist[i][j][j] = 0;
                while (!pq.empty()) {
                    auto pos = pq.top();
                    pq.pop();
                    if (dist[i][j][pos.second] < pos.first) continue;
                    for (auto k : g[pos.second]) {
                        int d = pos.first + ((i == 0) ? get<0>(k) : get<1>(k));
                        if (dist[i][j][get<2>(k)] == -1 || dist[i][j][get<2>(k)] > d) {
                            dist[i][j][get<2>(k)] = d;
                            pq.push({ d, get<2>(k) });
                        }
                    }
                }
            }
        }
        int k, p, q, r;
        cin >> k;
        while (k--) {
            cin >> p >> q >> r;
            cout << dist[r][p - 1][q - 1] << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3712
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;

constexpr int N = 1000;

void solve(int n, int m){
    vector<vector<long long>> GT(n, vector<long long>(n, 1ll<<60)), GC(n, vector<long long>(n, 1ll<<60));
    for(int i = 0; i < n; i++) GT[i][i] = GC[i][i] = 0;
    for(int i = 0; i < m; i++){
        int u, v, c, t;
        cin >> u >> v >> c >> t;
        u--; v--;
        GC[u][v] = GC[v][u] = min<long long>(GC[u][v], c);
        GT[u][v] = GT[v][u] = min<long long>(GT[u][v], t);
    }
    
    for(int k = 0; k < n; k++){
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                GC[i][j] = min(GC[i][j], GC[i][k] + GC[k][j]);
            }
        }
    }
    
    for(int k = 0; k < n; k++){
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                GT[i][j] = min(GT[i][j], GT[i][k] + GT[k][j]);
            }
        }
    }
    
    int q;
    cin >> q;
    while(q--){
        int t, u, v;
        cin >> u >> v >> t;
        u--; v--;
        if(t == 0) cout << GC[u][v] << '\n';
        else cout << GT[u][v] << '\n';
    }
}

int main(){
    cin.tie(0)->sync_with_stdio(0);
    int n, m;
    while(cin >> m >> n){
        if(m != 0 || n != 0) solve(n, m);
        else break;
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3576
final_rank: 9

code_snippet: //gemini

#include <iostream>
#include <vector>
#include <queue>
#include <limits>

// 無限大を表す定数
const int INF = std::numeric_limits<int>::max();

// 線路（グラフの辺）を表す構造体
struct Edge {
    int to;   // 隣接する駅
    int cost; // 金額
    int time; // 時間
};

// 駅の最大数 + 1
const int MAX_STATIONS = 1001;

// 隣接リストでグラフを表現
std::vector<Edge> adj[MAX_STATIONS];

// ダイクストラ法で最短経路を計算する関数
// start: 出発駅, end: 目的駅, type: 0なら金額、1なら時間, num_stations: 駅の総数
int dijkstra(int start, int end, int type, int num_stations) {
    // 各駅までの距離を記録する配列（INFで初期化）
    std::vector<int> dist(num_stations + 1, INF);
    
    // 優先度付きキュー（{距離, 駅} のペアを格納）
    // C++のpriority_queueはデフォルトで最大ヒープなので、最小ヒープにするためにgreaterを指定
    std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<std::pair<int, int>>> pq;

    // 出発駅の距離は0
    dist[start] = 0;
    pq.push({0, start});

    while (!pq.empty()) {
        // 現在地までの距離が最小の駅を取り出す
        int current_dist = pq.top().first;
        int u = pq.top().second;
        pq.pop();

        // より短い経路が既に見つかっている場合はスキップ
        if (current_dist > dist[u]) {
            continue;
        }

        // 目的駅に到達したら、その時点の距離を返す
        if (u == end) {
            return dist[end];
        }

        // 現在の駅から繋がっている全ての駅vについて
        for (const auto& edge : adj[u]) {
            int v = edge.to;
            // typeに応じて重み（金額か時間）を選択
            int weight = (type == 0) ? edge.cost : edge.time;
            
            // 現在の駅uを経由した場合の駅vへの距離が、記録されている距離より短いか調べる
            if (dist[u] != INF && dist[u] + weight < dist[v]) {
                // 短い経路が見つかったら距離を更新し、キューに追加
                dist[v] = dist[u] + weight;
                pq.push({dist[v], v});
            }
        }
    }
    // 基本的に経路は必ず存在するため、ここは通らない
    return dist[end];
}

int main() {
    // 高速な入出力
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    int n, m; // n: 線路の数, m: 駅の数

    // 複数のデータセットの処理
    // nとmが両方0になるまでループ
    while (std::cin >> n >> m && (n != 0 || m != 0)) {
        // 新しいデータセットのために隣接リストをクリア
        for (int i = 1; i <= m; ++i) {
            adj[i].clear();
        }

        // 線路の情報を読み込む
        for (int i = 0; i < n; ++i) {
            int a, b, cost, time;
            std::cin >> a >> b >> cost >> time;
            // 無向グラフなので、両方向の辺を追加
            adj[a].push_back({b, cost, time});
            adj[b].push_back({a, cost, time});
        }

        // 問い合わせの数を読み込む
        int k;
        std::cin >> k;

        // 各問い合わせを処理する
        for (int i = 0; i < k; ++i) {
            int p, q, r; // p: 出発駅, q: 到着駅, r: 問い合わせの種類
            std::cin >> p >> q >> r;
            std::cout << dijkstra(p, q, r, m) << "\n";
        }
    }

    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3464
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
 
constexpr int INF = 1e9;
 
int main() {
    int n, m;
    while(cin >> n >> m, n) {
        vector<vector<vector<int>>> d(2, vector<vector<int>>(m, vector<int>(m, INF)));
        for(int i=0; i<m; ++i) {
            d[0][i][i] = d[1][i][i] = 0;
        }
        for(int i=0; i<n; ++i) {
            int a, b, cost, time;
            cin >> a >> b >> cost >> time;
            a--; b--;
            d[0][a][b] = d[0][b][a] = cost;
            d[1][a][b] = d[1][b][a] = time;
        }
 
        for(int k=0; k<m; ++k) {
            for(int i=0; i<m; ++i) {
                for(int j=0; j<m; ++j) {
                    d[0][i][j] = min(d[0][i][j], d[0][i][k] + d[0][k][j]);
                    d[1][i][j] = min(d[1][i][j], d[1][i][k] + d[1][k][j]);
                }
            }
        }
 
        int k;
        cin >> k;
        for(int i=0; i<k; ++i) {
            int p, q, r;
            cin >> p >> q >> r;
            p--; q--;
            cout << d[r][p][q] << endl;
        }
    }
}
accuracy: 1
time_ms: 30
memory_kb: 3476
final_rank: 7

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <queue>
#include <map>
using namespace std;

struct Edge {
    int to, cost, time;
};

void dijkstra(int start, int m, vector<vector<Edge> >& graph, vector<int>& dist, bool isCost) {
    priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq; //優先度付きキューの宣言

    dist[start] = 0; //出発点の距離を0にする
    pq.push({0, start});

    while(!pq.empty()) {
        int d = pq.top().first; //現在ノードまでの距離
        int node = pq.top().second;
        pq.pop();

        if(d > dist[node]) continue; //取り出した距離が現在の値より大きければスキップ

        for(auto& edge : graph[node]) {
            int newDist = d + (isCost ? edge.cost : edge.time);
            if(newDist < dist[edge.to]) {
                dist[edge.to] = newDist;
                pq.push({newDist, edge.to});
            }
        }

    }

}



int main(void) {
    int n,m;
    while(cin >> n >> m, n != 0 && m != 0) {

        vector<vector<Edge> > graph(m+1);
        //グラフの作成
        for(int i = 0; i < n; i++) {
            int a, b, cost, time;
            cin >> a >> b >> cost >> time;
            graph[a].push_back({b, cost, time});
            graph[b].push_back({a, cost, time});
        }

        int k;
        cin >> k;
        while(k--) {
            int p, q, r;
            cin >> p >> q >> r;
            vector<int> dist(m+1, INT32_MAX);

            if(r == 0) {
                dijkstra(p, m, graph, dist, true); //コスト最小
            } else {
                dijkstra(p, m, graph, dist, false); //時間最短
            }

            cout << dist[q] << endl;
        }
    }


    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3464
final_rank: 11

code_snippet: #include <bits/stdc++.h>
#include<random>
#include<chrono>
using namespace std;

#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define Rrep(i,n) for(int i=n-1;i>=0;i--)
#define Rrep1(i,n) for(int i=n;i>0;i--)
#define all(a) a.begin(),a.end()
using ll = long long;
using ull = unsigned long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vl = vector<ll>;
using vvl = vector<vl>;
using vvvl = vector<vvl>;
#define INF ((ll)2e18)
#define IINF ((int)(1e9+5e8))
const double PI = 3.1415926535897932384626433832795028841971;
template<typename T>inline bool chmax(T& a, T b) { return ((a < b) ? (a = b, true) : (false)); }
template<typename T>inline bool chmin(T& a, T b) { return ((a > b) ? (a = b, true) : (false)); }
#define yesno(ans) cout<<((ans)?"Yes\n":"No\n")
bool eq(double a, double b) { return abs(a - b) < 0.0000001; }
//LRUD
//const int di[4] = { 0,-1,0,1 };
//const int dj[4] = { -1,0,1,0 };
const int di[8] = { 0,0,1,1,1,-1,-1,-1 };
const int dj[8] = { 1,-1,0,-1,1,0,-1,1 };

/*ACL
#include <atcoder/all>
using namespace atcoder;
//using mint=modint;
using mint = modint998244353;
//using mint = modint1000000007;
using vm = vector<mint>;
using vvm = vector<vm>;
using vvvm = vector<vvm>;
//*/

random_device seed_gen;
mt19937 rnd(seed_gen());



const int MAX_N=(int)2e5+10;//10余分に取ります
const int ST_SIZE=(1<<20)-1;

struct Edge{
    int to,cost;
    Edge(){}
    Edge(int to,int cost):to(to),cost(cost){}
};

vi dij(int s,vector<vector<Edge>> G){
    vi dist(G.size(),IINF);
    using P=pair<int,int>;
    priority_queue<P,vector<P>,greater<P>>q;
    q.emplace(0,s);
    while(!q.empty()){
        int cost=q.top().first;
        int pos=q.top().second;
        q.pop();
        if(dist[pos]<=cost)continue;
        dist[pos]=cost;
        for(auto [to,c]:G[pos]){
            if(dist[to]>cost+c)q.emplace(cost+c,to);
        }
    }
    return dist;
}
int solve() {
    int N,M;
    while(cin>>M>>N,N+M){
        vector<vector<Edge>> Gc(N),Gt(N);
        vvi dc(N,vi(N));
        vvi dt(N,vi(N));

        rep(i,M){
            int a,b;cin>>a>>b;
            int c,t;cin>>c>>t;
            a--,b--;
            Gt[a].emplace_back(b,t);
            Gt[b].emplace_back(a,t);
            Gc[a].emplace_back(b,c);
            Gc[b].emplace_back(a,c);
        }
        rep(i,N)dt[i]=dij(i,Gt);
        rep(i,N)dc[i]=dij(i,Gc);
        int K;cin>>K;
        while(K--){
            int p,q,r;cin>>p>>q>>r;
            p--,q--;
            int ans=0;
            if(r==0)ans=dc[p][q];
            else ans=dt[p][q];
            cout<<ans<<endl;
        }
    }
    return 0;
}

int main()
{
    //std::cin.tie(0)->sync_with_stdio(0);
    int T = 1;
    while (T--)
    {
        solve();
    }
    return 0;
}

/* 意気込み

*/
accuracy: 1
time_ms: 630
memory_kb: 3800
final_rank: 20

code_snippet: #line 1 "/opt/library/template.hpp"
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using i64 = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;

template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'000'001'000;
template <>
constexpr ll infty<ll> = ll(infty<int>) * infty<int> * 2;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * infty<ll>;
template <>
constexpr double infty<double> = infty<ll>;
template <>
constexpr long double infty<long double> = infty<ll>;
#define inf infty<ll>

using pi = pair<ll, ll>;
using vi = vector<ll>;
using vvi = vector<vector<ll>>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using vvvvvc = vector<vvvvc<T>>;
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;

#define vv(type, name, h, ...) \
  vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...)   \
  vector<vector<vector<type>>> name( \
      h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)       \
  vector<vector<vector<vector<type>>>> name( \
      a, vector<vector<vector<type>>>(       \
             b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))

#define rep1(a) for (ll _ = 0; _ < (ll)(a); ++_)
#define rep2(i, a) for (ll i = 0; i < (ll)(a); ++i)
#define rep3(i, a, b) for (ll i = a; i < (ll)(b); ++i)
#define rep4(i, a, b, c) for (ll i = a; i < (ll)(b); i += (c))
#define rrep1(a) for (ll i = (a)-1; i >= (ll)(0); --i)
#define rrep2(i, a) for (ll i = (a)-1; i >= (ll)(0); --i)
#define rrep3(i, a, b) for (ll i = (b)-1; i >= (ll)(a); --i)
#define rrep4(i, a, b, c) for (ll i = (b)-1; i >= (ll)(a); i -= (c))
#define overload4(a, b, c, d, e, ...) e
#define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)
#define rrep(...) overload4(__VA_ARGS__, rrep4, rrep3, rrep2, rrep1)(__VA_ARGS__)

#define all(x) (x).begin(),(x).end()
#define len(x) (ll)(x.size())
#define elif else if
#define bit(x, i) (((x)>>(i))&1)

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

#define stoi stoll
#define abs llabs

#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) \
  sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()

ll popcnt(ll x) { return __builtin_popcountll(x); }
ll popcnt(u64 x) { return __builtin_popcountll(x); }
ll popcnt_mod_2(ll x) { return __builtin_parityll(x); }
ll popcnt_mod_2(u64 x) { return __builtin_parityll(x); }
ll topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
ll topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
ll lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
ll lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }

template <typename T>
T floor(T a, T b) {
  return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
  return floor(x + y - 1, y);
}
template <typename T>
T bmod(T x, T y) {
  return x - y * floor(x, y);
}
template <typename T>
pair<T, T> divmod(T x, T y) {
  T q = floor(x, y);
  return {q, x - q * y};
}

template<typename T> T SUM(const vector<T> &A) {
  T s = 0; for (auto &&a: A) s += a;
  return s;
}

template <typename T>
T POP(queue<T> &que) {
  T a = que.front();
  que.pop();
  return a;
}
template <typename T>
T POP(deque<T> &que) {
  T a = que.front();
  que.pop_front();
  return a;
}
template <typename T>
T POP(pq<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(pqg<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(vc<T> &que) {
  T a = que.back();
  que.pop_back();
  return a;
}

template <typename F>
ll binary_search(F check, ll ok, ll ng, bool check_ok = true) {
  if (check_ok) assert(check(ok));
  while (abs(ok - ng) > 1) {
    auto x = (ng + ok) / 2;
    (check(x) ? ok : ng) = x;
  }
  return ok;
}
template <typename F>
f128 binary_search_real(F check, f128 ok, f128 ng, ll iter = 100) {
  rep(iter) {
    f128 x = (ok + ng) / 2;
    (check(x) ? ok : ng) = x;
  }
  return (ok + ng) / 2;
}

// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
  vc<int> A(S.size());
  rep(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
  return A;
}

template <typename T, typename U>
vc<T> cumsum(vc<U> &A, ll off = 1) {
  ll N = A.size();
  vc<T> B(N + 1);
  rep(i, N) { B[i + 1] = B[i] + A[i]; }
  if (off == 0) B.erase(B.begin());
  return B;
}

// stable sort
template <typename T>
vi argsort(const vector<T> &A) {
  vi ids(len(A));
  iota(all(ids), 0);
  sort(all(ids),
       [&](ll i, ll j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
  return ids;
}

// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vi &I) {
  vc<T> B(len(I));
  rep(i, len(I)) B[i] = A[I[i]];
  return B;
}

template<typename T> inline bool chmax(T &a, T b) {return ((a<b)?(a=b,true):(false));}
template<typename T> inline bool chmin(T &a, T b) {return ((a>b)?(a=b,true):(false));}

inline void wt(const char c) { cout << c; }
inline void wt(const string s) { cout << s; }
inline void wt(const char *s) { cout << s; }

template <typename T>
void wt_integer(T x) {
  cout << (x);
}
template <typename T>
void wt_real(T x) {
  cout << fixed << setprecision(15) << (long double)(x);
}
template <typename T>
void wt_integer128(T x) {
  char buf[64];
  char *d = end(buf);
  d--; *d = '\0';
  __uint128_t tmp = ((x < 0)? -x : x);
  do {
    d--; *d = char(tmp%10 + '0'); tmp /= 10;
  } while (tmp);
  if (x < 0) {
    d--; *d = '-';
  }
  cout << d;
}

inline void wt(int x) { wt_integer(x); }
inline void wt(ll x) { wt_integer(x); }
inline void wt(i128 x) { wt_integer128(x); }
inline void wt(u32 x) { wt_integer(x); }
inline void wt(u64 x) { wt_integer(x); }
inline void wt(u128 x) { wt_integer128(x); }
inline void wt(double x) { wt_real(x); }
inline void wt(long double x) { wt_real(x); }
inline void wt(f128 x) { wt_real(x); }

template <class T, class U>
void wt(const pair<T, U> val) {
  wt(val.first); wt(' '); wt(val.second);
}
template <size_t N = 0, typename T>
void wt_tuple(const T t) {
  if constexpr (N < std::tuple_size<T>::value) {
    if constexpr (N > 0) { wt(' '); }
    const auto x = std::get<N>(t);
    wt(x);
    wt_tuple<N + 1>(t);
  }
}
template <class... T>
void wt(tuple<T...> tpl) {
  wt_tuple(tpl);
}
template <class T, size_t S>
void wt(const array<T, S> val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}
template <class T>
void wt(const vector<T> val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}

void print() { wt('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
  wt(head);
  if (sizeof...(Tail)) wt(' ');
  print(forward<Tail>(tail)...);
}

void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
void onez(bool t = 1) { print(t ? 1 : 0); }
#define endl '\n'
#define dump(x) {cerr << #x " = " << x << '\n';}
#line 2 "/opt/library/graph/base.hpp"

template <typename T>
struct Edge {
  ll frm, to;
  T cost;
  ll id;
};

template <typename T = ll, bool directed = false>
struct Graph {
  static constexpr bool is_directed = directed;
  ll N, M;
  using cost_type = T;
  using edge_type = Edge<T>;
  vector<edge_type> edges;
  vi indptr;
  vc<edge_type> csr_edges;
  vc<ll> vc_deg, vc_indeg, vc_outdeg;
  bool prepared;

  class OutgoingEdges {
  public:
    OutgoingEdges(const Graph* G, ll l, ll r) : G(G), l(l), r(r) {}

    const edge_type* begin() const {
      if (l == r) { return 0; }
      return &G->csr_edges[l];
    }

    const edge_type* end() const {
      if (l == r) { return 0; }
      return &G->csr_edges[r];
    }

  private:
    const Graph* G;
    ll l, r;
  };

  bool is_prepared() { return prepared; }

  Graph() : N(0), M(0), prepared(0) {}
  Graph(ll N) : N(N), M(0), prepared(0) {}

  void build(ll n) {
    N = n, M = 0;
    prepared = 0;
    edges.clear();
    indptr.clear();
    csr_edges.clear();
    vc_deg.clear();
    vc_indeg.clear();
    vc_outdeg.clear();
  }

  void add(ll frm, ll to, T cost = 1, ll i = -1) {
    assert(!prepared);
    assert(0 <= frm && 0 <= to && to < N);
    if (i == -1) i = M;
    auto e = edge_type({frm, to, cost, i});
    edges.eb(e);
    ++M;
  }

#ifdef FASTIO
  // wt, off
  void read_tree(bool wt = false, ll off = 1) { read_graph(N - 1, wt, off); }

  void read_graph(ll M, bool wt = false, ll off = 1) {
    for (ll m = 0; m < M; ++m) {
      LL(a, b);
      a -= off, b -= off;
      if (!wt) {
        add(a, b);
      } else {
        T c;
        read(c);
        add(a, b, c);
      }
    }
    build();
  }
#endif

  void build() {
    assert(!prepared);
    prepared = true;
    indptr.assign(N + 1, 0);
    for (auto&& e: edges) {
      indptr[e.frm + 1]++;
      if (!directed) indptr[e.to + 1]++;
    }
    for (ll v = 0; v < N; ++v) { indptr[v + 1] += indptr[v]; }
    auto counter = indptr;
    csr_edges.resize(indptr.back() + 1);
    for (auto&& e: edges) {
      csr_edges[counter[e.frm]++] = e;
      if (!directed)
        csr_edges[counter[e.to]++] = edge_type({e.to, e.frm, e.cost, e.id});
    }
  }

  OutgoingEdges operator[](ll v) const {
    assert(prepared);
    return {this, indptr[v], indptr[v + 1]};
  }

  vi deg_array() {
    if (vc_deg.empty()) calc_deg();
    return vc_deg;
  }

  pair<vi, vi> deg_array_inout() {
    if (vc_indeg.empty()) calc_deg_inout();
    return {vc_indeg, vc_outdeg};
  }

  ll deg(ll v) {
    if (vc_deg.empty()) calc_deg();
    return vc_deg[v];
  }

  ll in_deg(ll v) {
    if (vc_indeg.empty()) calc_deg_inout();
    return vc_indeg[v];
  }

  ll out_deg(ll v) {
    if (vc_outdeg.empty()) calc_deg_inout();
    return vc_outdeg[v];
  }

#ifdef FASTIO
  void debug() {
    print("Graph");
    if (!prepared) {
      print("frm to cost id");
      for (auto&& e: edges) print(e.frm, e.to, e.cost, e.id);
    } else {
      print("indptr", indptr);
      print("frm to cost id");
      rep(v, N) for (auto&& e: (*this)[v]) print(e.frm, e.to, e.cost, e.id);
    }
  }
#endif

  vi new_idx;
  vc<bool> used_e;

  // G における頂点 V[i] が、新しいグラフで i になるようにする
  // {G, es}
  Graph<T, directed> rearrange(vi V, bool keep_eid = 0) {
    if (len(new_idx) != N) new_idx.assign(N, -1);
    if (len(used_e) != M) used_e.assign(M, 0);
    ll n = len(V);
    rep(i, n) new_idx[V[i]] = i;
    Graph<T, directed> G(n);
    vi history;
    rep(i, n) {
      for (auto&& e: (*this)[V[i]]) {
        if (used_e[e.id]) continue;
        ll a = e.frm, b = e.to;
        if (new_idx[a] != -1 && new_idx[b] != -1) {
          history.eb(e.id);
          used_e[e.id] = 1;
          ll eid = (keep_eid ? e.id : -1);
          G.add(new_idx[a], new_idx[b], e.cost, eid);
        }
      }
    }
    rep(i, n) new_idx[V[i]] = -1;
    for (auto&& eid: history) used_e[eid] = 0;
    G.build();
    return G;
  }

private:
  void calc_deg() {
    assert(vc_deg.empty());
    vc_deg.resize(N);
    for (auto&& e: edges) vc_deg[e.frm]++, vc_deg[e.to]++;
  }

  void calc_deg_inout() {
    assert(vc_indeg.empty());
    vc_indeg.resize(N);
    vc_outdeg.resize(N);
    for (auto&& e: edges) { vc_indeg[e.to]++, vc_outdeg[e.frm]++; }
  }
};
#line 3 "/opt/library/graph/shortest_path/dijkstra.hpp"

template <typename T, typename GT>
pair<vc<T>, vi> dijkstra_dense(GT& G, ll s) {
  const ll N = G.N;
  vc<T> dist(N, infty<T>);
  vi par(N, -1);
  vc<bool> done(N);
  dist[s] = 0;
  while (1) {
    ll v = -1;
    T mi = infty<T>;
    rep(i, N) {
      if (!done[i] && chmin(mi, dist[i])) v = i;
    }
    if (v == -1) break;
    done[v] = 1;
    for (auto&& e: G[v]) {
      if (chmin(dist[e.to], dist[v] + e.cost)) par[e.to] = v;
    }
  }
  return {dist, par};
}

template <typename T, typename GT, bool DENSE = false>
pair<vc<T>, vi> dijkstra(GT& G, ll v) {
  if (DENSE) return dijkstra_dense<T>(G, v);
  auto N = G.N;
  vc<T> dist(N, infty<T>);
  vi par(N, -1);
  using P = pair<T, ll>;

  priority_queue<P, vector<P>, greater<P>> que;

  dist[v] = 0;
  que.emplace(0, v);
  while (!que.empty()) {
    auto [dv, v] = que.top();
    que.pop();
    if (dv > dist[v]) continue;
    for (auto&& e: G[v]) {
      if (chmin(dist[e.to], dist[e.frm] + e.cost)) {
        par[e.to] = e.frm;
        que.emplace(dist[e.to], e.to);
      }
    }
  }
  return {dist, par};
}

// 多点スタート。[dist, par, root]
template <typename T, typename GT>
tuple<vc<T>, vi, vi> dijkstra(GT& G, vi vs) {
  assert(G.is_prepared());
  ll N = G.N;
  vc<T> dist(N, infty<T>);
  vi par(N, -1);
  vi root(N, -1);

  using P = pair<T, ll>;

  priority_queue<P, vector<P>, greater<P>> que;

  for (auto&& v: vs) {
    dist[v] = 0;
    root[v] = v;
    que.emplace(T(0), v);
  }

  while (!que.empty()) {
    auto [dv, v] = que.top();
    que.pop();
    if (dv > dist[v]) continue;
    for (auto&& e: G[v]) {
      if (chmin(dist[e.to], dist[e.frm] + e.cost)) {
        root[e.to] = root[e.frm];
        par[e.to] = e.frm;
        que.push(mp(dist[e.to], e.to));
      }
    }
  }
  return {dist, par, root};
}
#line 3 "main.cpp"

int solve();
int main() {
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  while (!solve()) {}
  return 0;
}

int solve() {
  ll n, m, a, b, c, t, k, p, q, r;;
  cin >> n >> m;
  if (n == 0 && m == 0) {return 1;}
  Graph<ll> GC(m), GT(m);
  rep(n) {
    cin >> a >> b >> c >> t;
    --a, --b;
    GC.add(a, b, c);
    GT.add(a, b, t);
  }
  GC.build();
  GT.build();
  cin >> k;
  rep(k) {
    cin >> p >> q >> r;
    --p, --q;
    if (r == 0) {
      print(dijkstra<ll>(GC, p).fi[q]);
    } else {
      print(dijkstra<ll>(GT, p).fi[q]);
    }
  }
  return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3592
final_rank: 15

code_snippet: #pragma region Macros

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,fma,abm,mmx,avx,avx2")

#include <bits/extc++.h>
// #include <atcoder/all>
// using namespace atcoder;
using namespace std;
using namespace __gnu_pbds;

// #include <boost/multiprecision/cpp_dec_float.hpp>
// #include <boost/multiprecision/cpp_int.hpp>
// namespace mp = boost::multiprecision;
// using Bint = mp::cpp_int;
// using Bdouble = mp::number<mp::cpp_dec_float<256>>;
// Bdouble Beps = 0.00000000000000000000000000000001; // 1e-32
// const bool equals(Bdouble a, Bdouble b) { return mp::fabs(a - b) < Beps; }

#define pb emplace_back
#define int ll
#define endl '\n'
// #define unordered_map<int, int> gp_hash_table<int, int, custom_hash> 

#define sqrt __builtin_sqrtl
#define cbrt __builtin_cbrtl
#define hypot __builtin_hypotl

#define next asdnext
#define prev asdprev

using ll = long long;
using ld = long double;
const ld PI = acosl(-1);
const int INF = 1 << 30;
const ll INFL = 1LL << 61;
// const int MOD = 998244353;
const int MOD = 1000000007;

const ld EPS = 1e-10;
const bool equals(ld a, ld b) { return fabs((a) - (b)) < EPS; }

const vector<int> dx = {0, 1, 0, -1, 1, 1, -1, -1}; // → ↓ ← ↑ ↘ ↙ ↖ ↗
const vector<int> dy = {1, 0, -1, 0, 1, -1, -1, 1};

struct Edge {
    int from, to;
    double cost;
    Edge() : from(-1), to(-1), cost(-1) {}
    Edge(int to, double cost) : to(to), cost(cost) {}
    Edge(int from, int to, double cost) : from(from), to(to), cost(cost) {}
    bool operator ==(const Edge& e) {
        return this->from == e.from && this->to == e.to && this->cost == e.cost;
    }
    bool operator !=(const Edge& e) {
        return this->from != e.from or this->to != e.to or this->cost != e.cost;
    }
};

chrono::system_clock::time_point start;
__attribute__((constructor))
void constructor() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(10);
    start = chrono::system_clock::now();
}

random_device seed_gen;
mt19937_64 rng(seed_gen());
uniform_int_distribution<int> dist_x(0, 1e9);
struct RNG {
    unsigned Int(unsigned l, unsigned r) {
        return dist_x(rng) % (r - l + 1) + l;
    }
    ld Double() {
        return ld(dist_x(rng)) / 1e9;
    }
} rnd;

using i64 = ll;
// using i64 = uint64_t;
// bit演算, x==0の場合は例外処理した方がよさそう. 区間は [l, r)
i64 lrmask(i64 l, i64 r) { return (1LL << r) - (1LL << l); }
i64 sub_bit(i64 x, i64 l, i64 r) { i64 b = x & ((1LL << r) - (1LL << l)); return b >> l; } // r溢れ可
i64 bit_width(i64 x) { return 64 - __builtin_clzll(x) + (x == 0); }

i64 popcount(i64 x) { return __builtin_popcountll(x); }
i64 popcount(i64 x, i64 l, i64 r) { return __builtin_popcountll(sub_bit(x, l, r)); }
i64 unpopcount(i64 x) { return bit_width(x) - __builtin_popcountll(x); }
i64 unpopcount(i64 x, i64 l, i64 r) { return r - l - __builtin_popcountll(sub_bit(x, l, r)); }
bool is_pow2(i64 x) { return __builtin_popcountll(x) == 1; }

i64 top_bit(i64 x) { return 63 - __builtin_clzll(x);} // 2^kの位 (x > 0)
i64 bot_bit(i64 x) { return __builtin_ctz(x);} // 2^kの位 (x > 0)
// i64 next_bit(i64 x, i64 k) { return 0; }
// i64 prev_bit(i64 x, i64 k) { return 0; }
// i64 kth_bit(i64 x, i64 k) { return 0; }
i64 MSB(i64 x) { if (x == 0) return 0; return 1LL << (63 - __builtin_clzll(x)); } // mask
i64 LSB(i64 x) { return (x & -x); } // mask

i64 countl_zero(i64 x) { return __builtin_clzll(x); }
i64 countl_one(i64 x) {
    i64 ret = 0, k = 63 - __builtin_clzll(x);
    while (k != -1 && (x & (1LL << k))) { k--; ret++; }
    return ret;
}
i64 countr_zero(i64 x) { return __builtin_ctzll(x); } // x==0のとき64が返ることに注意
i64 countr_one(i64 x) { i64 ret = 0; while (x & 1) { x >>= 1; ret++; } return ret; }

i64 floor_log2(i64 x) { if (x == 0) return 0; return 63 - __builtin_clzll(x); }
i64 bit_floor(i64 x) { if (x == 0) return 0; return 1LL << (63 - __builtin_clzll(x)); } // MSBと同じ
i64 ceil_log2(i64 x) { if (x == 0) return 0; return 64 - __builtin_clzll(x - 1); }
i64 bit_ceil(i64 x) { if (x == 0) return 0; return 1LL << (64 - __builtin_clzll(x - 1)); }

i64 rotl(i64 x, i64 k) { // 有効bit内でrotate. オーバーフロー注意
    i64 w = bit_width(x); k %= w;
    return ((x << k) | (x >> (w - k))) & ((1LL << w) - 1);
}
// i64 rotl(i64 x, i64 l, i64 m, i64 r) {}
i64 rotr(i64 x, i64 k) {
    i64 w = bit_width(x); k %= w;
    return ((x >> k) | (x << (w - k))) & ((1LL << w) - 1);
}
// i64 rotr(i64 x, i64 l, i64 m, i64 r) {}
i64 bit_reverse(i64 x) { // 有効bit内で左右反転
    i64 r = 0, w = bit_width(x);
    for (i64 i = 0; i < w; i++) r |= ((x >> i) & 1) << (w - i - 1);
    return r;
}
// i64 bit_reverse(i64 x, i64 l, i64 r) { return 0; }

bool is_palindrome(i64 x) { return x == bit_reverse(x); }
bool is_palindrome(i64 x, i64 l, i64 r) { i64 b = sub_bit(x, l, r); return b == bit_reverse(b); }
i64 concat(i64 a, i64 b) { return (a << bit_width(b)) | b; } // オーバーフロー注意
i64 erase(i64 x, i64 l, i64 r) { return x>>r<<l | x&(1LL<<l - 1); } // [l, r) をカット

i64 hamming(i64 a, i64 b) { return __builtin_popcountll(a ^ b); }
i64 hamming(i64 a, i64 b, i64 l, i64 r) { return __builtin_popcountll(sub_bit(a, l, r) ^ sub_bit(b, l, r)); }
i64 compcount(i64 x) { return (__builtin_popcountll(x ^ (x >> 1)) + (x & 1)) / 2; }
i64 compcount2(i64 x) { return compcount(x & (x >> 1)); } // 長さ2以上の連結成分の個数
i64 adjacount(i64 x) { return __builtin_popcountll(x & (x >> 1)); } // 隣接する1のペアの個数

i64 next_combination(i64 x) {
    i64 t = x | (x - 1); return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(x) + 1));
}


__int128_t POW(__int128_t x, int n) {
    __int128_t ret = 1;
    assert(n >= 0);
    if (x == 1 or n == 0) ret = 1;
    else if (x == -1 && n % 2 == 0) ret = 1; 
    else if (x == -1) ret = -1; 
    else if (n % 2 == 0) {
        assert(x < INFL);
        ret = POW(x * x, n / 2);
    } else {
        assert(x < INFL);
        ret = x * POW(x, n - 1);
    }
    return ret;
}
int per(int x, int y) { // x = qy + r (0 <= r < y) を満たすq
    assert(y != 0);
    if (x >= 0 && y > 0) return x / y;
    if (x >= 0 && y < 0) return x / y - (x % y < 0);
    if (x < 0 && y < 0) return x / y + (x % y < 0);
    return x / y - (x % y < 0); //  (x < 0 && y > 0) 
}
int mod(int x, int y) { // x = qy + r (0 <= r < y) を満たすr
    assert(y != 0);
    if (x >= 0) return x % y;
    __int128_t ret = x % y; // (x < 0)
    ret += (__int128_t)abs(y) * INFL;
    ret %= abs(y);
    return ret;
}
int floor(int x, int y) { // (ld)x / y 以下の最大の整数
    assert(y != 0);
    if (y < 0) x = -x, y = -y;
    return x >= 0 ? x / y : (x + 1) / y - 1;
}
int ceil(int x, int y) { // (ld)x / y 以上の最小の整数
    assert(y != 0);
    if (y < 0) x = -x, y = -y;
    return x > 0 ? (x - 1) / y + 1 : x / y;
}
int round(int x, int y) {
    assert(y != 0);
    return (x * 2 + y) / (y * 2);
}
int round(int x, int y, int k) { // (ld)(x/y)を10^kの位に関して四捨五入
    assert(y != 0); // TODO
    return INF;
}
int round2(int x, int y) { // 五捨五超入 // 未verify
    assert(y != 0);
    if (y < 0) y = -y, x = -x;
    int z = z / y;
    if ((z * 2 + 1) * y <= y * 2) z++;
    return z;
}
// int round(ld x, int k) { // xを10^kの位に関して四捨五入
// }
// int floor(ld x, int k) { // xを10^kの位に関してflooring
// }
// int ceil(ld x, int k) { // xを10^kの位に関してceiling
// }
// int kth(int x, int y, int k) { // x / yの10^kの位の桁
// }
int floor(ld x, ld y) { // 誤差対策TODO
    assert(!equals(y, 0));
    return floor(x / y);
    // floor(x) = ceil(x - 1) という話も
}
int ceil(ld x, ld y) { // 誤差対策TODO // ceil(p/q) = -floor(-(p/q))らしい
    assert(!equals(y, 0));
    return ceil(x / y);
    // ceil(x) = floor(x + 1)
}
int perl(ld x, ld y) { // x = qy + r (0 <= r < y, qは整数) を満たす q
    // 未verify. 誤差対策TODO. EPS外してもいいかも。
    assert(!equals(y, 0));
    if (x >= 0 && y > 0) return floor(x / y)+EPS;
    if (x >= 0 && y < 0) return -floor(x / fabs(y));
    if (x < 0 && y < 0) return floor(x / y) + (x - floor(x/y)*y < -EPS);
    return floor(x / y) - (x - floor(x/y)*y < -EPS); //  (x < 0 && y > 0) 
}
ld modl(ld x, ld y) { // x = qy + r (0 <= r < y, qは整数) を満たす r
    // 未verify. 誤差対策TODO. -0.0が返りうる。
    assert(!equals(y, 0));
    if (x >= 0) return x - fabs(y)*fabs(per(x, y));
    return x - fabs(y)*floor(x, fabs(y));
}
int seisuu(ld x) { return (int)x; } // 整数部分. 誤差対策TODO
int modf(ld x) {
	if (x < 0) return ceill(x);
	else return floorl(x);
}
// 正なら+EPS, 負なら-EPSしてから、文字列に直して小数点以下を捨てる?
int seisuu(int x, int y) {
    assert(y != 0);
    return x / y;
}
int seisuu(ld x, ld y) { // 誤差対策TODO
    assert(!equals(y, 0));
    return (int)(x / y);
}

template <class T> pair<T, T> max(const pair<T, T> &a, const pair<T, T> &b) {
    if (a.first > b.first or a.first == b.first && a.second > b.second) return a;
    return b;
}
template <class T> pair<T, T> min(const pair<T, T> &a, const pair<T, T> &b) {
    if (a.first < b.first or a.first == b.first && a.second < b.second) return a;
    return b;
}

template <class T> bool chmax(T &a, const T& b) {
    if (a < b) { a = b; return true; } return false;
}
template <class T> bool chmin(T &a, const T& b) {
    if (a > b) { a = b; return true; } return false;
}
template <class T> T mid(T a, T b, T c) { // 誤差対策TODO
    return a + b + c - max({a, b, c}) - min({a, b, c});
}
template <class T> void Sort(T &a, T &b, bool rev = false) { 
    if (rev == false) {  // TODO テンプレート引数
        if (a > b) swap(a, b);
    } else {
        if (b > a) swap(b, a);
    }
}
template <class T> void sort(T &a, T &b, T &c, bool rev = false) {
    if (rev == false) { 
        if (a > b) swap(a, b); if (a > c) swap(a, c); if (b > c) swap(b, c);
    } else {
        if (c > b) swap(c, b); if (c > a) swap(c, a); if (b > a) swap(b, a);
    }
}
template <class T> void sort(T &a, T &b, T &c, T &d, bool rev = false) {
    if (rev == false) { 
        if (a > b) swap(a, b); if (a > c) swap(a, c);  if (a > d) swap(a, d);
        if (b > c) swap(b, c); if (b > d) swap(b, d); if (c > d) swap(c, d);
    } else {
        if (d > c) swap(d, c); if (d > b) swap(d, b); if (d > a) swap(d, a);
        if (c > b) swap(c, b); if (c > a) swap(c, a); if (b > a) swap(b, a);
    }
}

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

class Compress {
public:
    int sz = 0;
    // gp_hash_table<int, int, custom_hash> Z, UZ;
    unordered_map<int, int> Z;    // 元の値 -> 圧縮した値
    unordered_map<int, int> UZ;   // 圧縮した値 -> 元の値

    Compress(const vector<int> &V, int base = 0) {
        this->sz = base;
        set<int> s(V.begin(), V.end());

        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }
    
    Compress(const vector<int> &V1, const vector<int> &V2, int base = 0) {
        this->sz = base;
        vector<int> V3 = V2;
        V3.insert(V3.end(), V1.begin(), V1.end());
        set<int> s(V3.begin(), V3.end());

        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }

    Compress(const vector<int> &V1, const vector<int> &V2, const vector<int> &V3, int base = 0) {
        this->sz = base;
        vector<int> V4 = V1;
        V4.insert(V4.end(), V2.begin(), V2.end());
        V4.insert(V4.end(), V3.begin(), V3.end());
        set<int> s(V4.begin(), V4.end());

        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }

    Compress(const vector<int> &V1, const vector<int> &V2,
            const vector<int> &V3, const vector<int> &V4, int base = 0) {
        this->sz = base;
        vector<int> V5 = V1;
        V5.insert(V5.end(), V2.begin(), V2.end());
        V5.insert(V5.end(), V3.begin(), V3.end());
        V5.insert(V5.end(), V4.begin(), V4.end());
        set<int> s(V5.begin(), V5.end());

        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }

    vector<int> zip(const vector<int> &V) {
        vector<int> ret = V;
        for (int i = 0; i < (int)V.size(); i++) {
            ret[i] = Z[ret[i]];
        }
        return ret;
    }

    vector<int> unzip(const vector<int> &V) {
        vector<int> ret = V;
        for (int i = 0; i < (int)V.size(); i++) {
            ret[i] = UZ[ret[i]];
        }
        return ret;
    }

    int size() { return sz; }

    int encode(int x) { return Z[x]; }
    int decode(int x) {
        if (UZ.find(x) == UZ.end()) return -1; // xが元の配列に存在しないとき
        return UZ[x];
    }
};

class UnionFind {
public:
	UnionFind() = default;
    UnionFind(int N) : par(N), sz(N, 1) {
        iota(par.begin(), par.end(), 0);
    }
	int root(int x) {
		if (par[x] == x) return x;
		return (par[x] = root(par[x]));
	}
	bool unite(int x, int y) {
		int rx = root(x);
		int ry = root(y);
        if (rx == ry) return false;
		if (sz[rx] < sz[ry]) swap(rx, ry);
		sz[rx] += sz[ry];
		par[ry] = rx;
        return true;
	}
	bool issame(int x, int y) { return (root(x) == root(y)); }
	int size(int x) { return sz[root(x)]; }
    vector<vector<int>> groups(int N) {
        vector<vector<int>> G(N);
        for (int x = 0; x < N; x++) {
            G[root(x)].push_back(x);
        }
		G.erase( remove_if(G.begin(), G.end(),
            [&](const vector<int>& V) { return V.empty(); }), G.end());
        return G;
    }
private:
	vector<int> par, sz;
};

template<typename T>
struct BIT {
    int N;             // 要素数
    vector<T> bit[2];  // データの格納先
    BIT(int N_, int x = 0) {
        N = N_ + 1;
        bit[0].assign(N, 0); bit[1].assign(N, 0);
        if (x != 0) {
            for (int i = 0; i < N; i++) add(i, x);
        }
    }
    BIT(const vector<int> &A) {
        N = A.size() + 1;
        bit[0].assign(N, 0); bit[1].assign(N, 0);
        for (int i = 0; i < (int)A.size(); i++) add(i, A[i]);
    }
    void add_sub(int p, int i, T x) {
        while (i < N) { bit[p][i] += x; i += (i & -i); }
    }
    void add(int l, int r, T x) {
        add_sub(0, l + 1, -x * l); add_sub(0, r + 1, x * r);
        add_sub(1, l + 1, x); add_sub(1, r + 1, -x);
    }
    void add(int i, T x) { add(i, i + 1, x); }
    T sum_sub(int p, int i) {
        T ret = 0;
        while (i > 0) { ret += bit[p][i]; i -= (i & -i); }
        return ret;
    }
    T sum(int i) { return sum_sub(0, i) + sum_sub(1, i) * i; }
    T sum(int l, int r) { return sum(r) - sum(l); }
    T get(int i) { return sum(i, i + 1); }
    void set(int i, T x) { T s = get(i); add(i, -s + x); }
};

template<int mod> class Modint {
public:
    int val = 0;
    Modint(int x = 0) { while (x < 0) x += mod; val = x % mod; }
    Modint(const Modint &r) { val = r.val; }

    Modint operator -() { return Modint(-val); } // 単項
    Modint operator +(const Modint &r) { return Modint(*this) += r; }
    Modint operator +(const int &q) { Modint r(q); return Modint(*this) += r; }
    Modint operator -(const Modint &r) { return Modint(*this) -= r; }
    Modint operator -(const int &q) { Modint r(q); return Modint(*this) -= r; }
    Modint operator *(const Modint &r) { return Modint(*this) *= r; }
    Modint operator *(const int &q) { Modint r(q); return Modint(*this) *= r; }
    Modint operator /(const Modint &r) { return Modint(*this) /= r; }
    Modint operator /(const int &q) { Modint r(q); return Modint(*this) /= r; }
    
    Modint& operator ++() { val++; if (val >= mod) val -= mod; return *this; } // 前置
    Modint operator ++(signed) { ++*this; return *this; } // 後置
    Modint& operator --() { val--; if (val < 0) val += mod; return *this; }
    Modint operator --(signed) { --*this; return *this; }
    Modint &operator +=(const Modint &r) { val += r.val; if (val >= mod) val -= mod; return *this; }
    Modint &operator +=(const int &q) { Modint r(q); val += r.val; if (val >= mod) val -= mod; return *this; }
    Modint &operator -=(const Modint &r) { if (val < r.val) val += mod; val -= r.val; return *this; }
    Modint &operator -=(const int &q) { Modint r(q);  if (val < r.val) val += mod; val -= r.val; return *this; }
    Modint &operator *=(const Modint &r) { val = val * r.val % mod; return *this; }
    Modint &operator *=(const int &q) { Modint r(q); val = val * r.val % mod; return *this; }
    Modint &operator /=(const Modint &r) {
        int a = r.val, b = mod, u = 1, v = 0;
        while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}
        val = val * u % mod; if (val < 0) val += mod;
        return *this;
    }
    Modint &operator /=(const int &q) {
        Modint r(q); int a = r.val, b = mod, u = 1, v = 0;
        while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}
        val = val * u % mod; if (val < 0) val += mod;
        return *this;
    }
    bool operator ==(const Modint& r) { return this -> val == r.val; }
    bool operator <(const Modint& r) { return this -> val < r.val; }
    bool operator >(const Modint& r) { return this -> val > r.val; }
    bool operator !=(const Modint& r) { return this -> val != r.val; }
};

using mint = Modint<MOD>;

istream &operator >>(istream &is, mint& x) {
    int t; is >> t; x = t; return (is);
}
ostream &operator <<(ostream &os, const mint& x) {
    return os << x.val;
}
mint modpow(const mint &x, int n) {
    if (n < 0) return (mint)1 / modpow(x, -n); // 未verify
    assert(n >= 0);
    if (n == 0) return 1;
    mint t = modpow(x, n / 2);
    t = t * t;
    if (n & 1) t = t * x;
    return t;
}

int modpow(__int128_t x, int n, int mod) {
    assert(n >= 0 && mod > 0); // TODO: n <= -1
    __int128_t ret = 1;
    while (n > 0) {
        if (n % 2 == 1) ret = ret * x % mod;
        x = x * x % mod;
        n /= 2;
    }
    return ret;
}
int modinv(__int128_t x, int mod) {
    assert(mod > 0);
    // assert(x > 0);
    if (x == 1 or x == 0) return 1;
    return mod - modinv(mod % x, mod) * (mod / x) % mod;
}

istream &operator >>(istream &is, __int128_t& x) {
    string S; is >> S;
    __int128_t ret = 0;
    int f = 1;
    if (S[0] == '-') f = -1; 
    for (int i = 0; i < S.length(); i++)
        if ('0' <= S[i] && S[i] <= '9')
            ret = ret * 10 + S[i] - '0';
    x = ret * f;
    return (is);
}
ostream &operator <<(ostream &os, __int128_t x) {
    ostream::sentry s(os);
    if (s) {
        __uint128_t tmp = x < 0 ? -x : x;
        char buffer[128]; char *d = end(buffer);
        do {
            --d; *d = "0123456789"[tmp % 10]; tmp /= 10;
        } while (tmp != 0);
        if (x < 0) { --d; *d = '-'; }
        int len = end(buffer) - d;
        if (os.rdbuf()->sputn(d, len) != len) os.setstate(ios_base::badbit);
    }
    return os;
}

__int128_t stoll(string &S) {
    __int128_t ret = 0; int f = 1;
    if (S[0] == '-') f = -1; 
    for (int i = 0; i < S.length(); i++)
        if ('0' <= S[i] && S[i] <= '9') ret = ret * 10 + S[i] - '0';
    return ret * f;
}
__int128_t gcd(__int128_t a, __int128_t b) { return b ? gcd(b, a % b) : a; }
__int128_t lcm(__int128_t a, __int128_t b) {
    return a / gcd(a, b) * b;
    // lcmが__int128_tに収まる必要あり
}

string to_string(ld x, int k) { // xの小数第k位までをstring化する
    assert(k >= 0);
    stringstream ss;
    ss << setprecision(k + 2) << x;
    string s = ss.str();
    if (s.find('.') == string::npos) s += '.';
    int pos = s.find('.');
    for (int i = 0; k >= (int)s.size() - 1 - pos; i++) s += '0';
    s.pop_back();
    if (s.back() == '.') s.pop_back();
    return s;

    // stringstream ss; // 第k+1位を四捨五入して第k位まで返す
    // ss << setprecision(k + 1) << x;
    // string s = ss.str();
    // if (s.find('.') == string::npos) s += '.';
    // int pos = s.find('.');
    // for (int i = 0; k > (int)s.size() - 1 - pos; i++) s += '0';
    // if (s.back() == '.') s.pop_back();
    // return s;
}
string to_string(__int128_t x) {
    string ret = "";
    if (x < 0) { ret += "-"; x *= -1; }
    while (x) { ret += (char)('0' + x % 10); x /= 10; }
    reverse(ret.begin(), ret.end());
    return ret;
}
string to_string(char c) { string s = ""; s += c; return s; }

template<class T> size_t HashCombine(const size_t seed,const T &v) {
    return seed^(hash<T>()(v)+0x9e3779b9+(seed<<6)+(seed>>2));
}
template<class T,class S> struct hash<pair<T,S>>{
    size_t operator()(const pair<T,S> &keyval) const noexcept {
        return HashCombine(hash<T>()(keyval.first), keyval.second);
    }
};
template<class T> struct hash<vector<T>>{
    size_t operator()(const vector<T> &keyval) const noexcept {
        size_t s=0;
        for (auto&& v: keyval) s=HashCombine(s,v);
        return s;
    }
};
template<int N> struct HashTupleCore{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{
        size_t s=HashTupleCore<N-1>()(keyval);
        return HashCombine(s,get<N-1>(keyval));
    }
};
template <> struct HashTupleCore<0>{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{ return 0; }
};
template<class... Args> struct hash<tuple<Args...>>{
    size_t operator()(const tuple<Args...> &keyval) const noexcept {
        return HashTupleCore<tuple_size<tuple<Args...>>::value>()(keyval);
    }
};

vector<mint> _fac, _finv, _inv;
void COMinit(int N) {
    _fac.resize(N + 1); _finv.resize(N + 1);  _inv.resize(N + 1);
    _fac[0] = _fac[1] = 1; _finv[0] = _finv[1] = 1; _inv[1] = 1;
    for (int i = 2; i <= N; i++) {
        _fac[i] = _fac[i-1] * mint(i);
        _inv[i] = -_inv[MOD % i] * mint(MOD / i);
        _finv[i] = _finv[i - 1] * _inv[i];
    }
}

mint FAC(int N) {
    if (N < 0) return 0; return _fac[N];
}
mint COM(int N, int K) {
    if (N < K) return 0; if (N < 0 or K < 0) return 0;
    return _fac[N] * _finv[K] * _finv[N - K];
}
mint PERM(int N, int K) {
    if (N < K) return 0; if (N < 0 or K < 0) return 0;
    return _fac[N] *  _finv[N - K];
}
mint NHK(int N, int K) { // initのサイズに注意
    if (N == 0 && K == 0)  return 1;
    return COM(N + K - 1, K);
}

#pragma endregion

vector<string> split_str(string S, char c) {
    vector<string> ret;
    stringstream ss;
    for (int i = 0; i < S.size(); i++) {
        if (S[i] == c) {
            ret.pb(ss.str());
            ss.str("");
            ss.clear();
        } else {
            ss << S[i];
        }
    }
    ret.pb(ss.str());
    return ret;
}

signed main() {
    int N, M;
    while (cin >> M >> N, N) {
        vector<vector<Edge>> Gc(N), Gt(N);
        for (int i = 0; i < M; i++) {
            int u, v, c, t;
            cin >> u >> v >> c >> t;
            u--; v--;
            Gc[u].pb(Edge(v, c));
            Gc[v].pb(Edge(u, c));
            Gt[u].pb(Edge(v, t));
            Gt[v].pb(Edge(u, t));
        }

        int Q;
        cin >> Q;
        for (int q = 0; q < Q; q++) {
            int s, t, ty;
            cin >> s >> t >> ty;
            s--; t--;
            if (ty == 0) {
                vector<int> dist(N, INFL);
                dist[s] = 0;
                
                std::priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
                pq.emplace(0, s);
                // for (int i = 0; i < N; i++) pq.emplace(dist[i], i);
                
                while (pq.size()) {
                    int d = pq.top().first;
                    int v = pq.top().second;
                    pq.pop();
                    if (v == t) break;
                    if (d > dist[v]) continue;
                    for (auto &e : Gc[v]) {
                        if (dist[e.to] > dist[v] + e.cost) {
                            dist[e.to] = dist[v] + e.cost;
                            pq.emplace(dist[e.to], e.to);
                        }
                    }
                }
                cout << dist[t] << endl;
            } else {
                vector<int> dist(N, INFL);
                dist[s] = 0;
                
                std::priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
                pq.emplace(0, s);
                // for (int i = 0; i < N; i++) pq.emplace(dist[i], i);
                
                while (pq.size()) {
                    int d = pq.top().first;
                    int v = pq.top().second;
                    pq.pop();
                    if (v == t) break;
                    if (d > dist[v]) continue;
                    for (auto &e : Gt[v]) {
                        if (dist[e.to] > dist[v] + e.cost) {
                            dist[e.to] = dist[v] + e.cost;
                            pq.emplace(dist[e.to], e.to);
                        }
                    }
                }
                cout << dist[t] << endl;
            }
        }
    }
}
accuracy: 1
time_ms: 50
memory_kb: 3880
final_rank: 18

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, m;
    while (cin >> n >> m, n+m) {
        const int inf = 1e9;
        vector<vector<int>> d(m, vector<int>(m, inf));
        auto e = d;
        for (int i = 0; i < m; ++i) {
            d[i][i] = e[i][i] = 0;
        }
        for (int i = 0; i < n; ++i) {
            int a,b,c,t; cin >> a >> b >> c >> t;
            a--; b--;
            d[a][b] = min(d[a][b], c);
            d[b][a] = min(d[b][a], c);
            e[a][b] = min(e[a][b], t);
            e[b][a] = min(e[b][a], t);
        }
        for (int k = 0; k < m; ++k) {
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < m; ++j) {
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
                    e[i][j] = min(e[i][j], e[i][k] + e[k][j]);
                }
            }
        }
        int k; cin >> k;
        for (int i = 0; i < k; ++i) {
            int p,q,r; cin >> p >> q >> r;
            p--; q--;
            if (r == 0) {
                cout << d[p][q] << endl;
            }
            else {
                cout << e[p][q] << endl;
            }
        }
    }
}
accuracy: 1
time_ms: 30
memory_kb: 3472
final_rank: 6

code_snippet: //Source.cpp
//いつもの
#ifdef LOCAL
#define _USE_MATH_DEFINES
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<list>
#include<algorithm>
#include<numeric>
#include<cmath>
#include<climits>
#include<iomanip>
#include<cctype>
#include<sstream>
#include<regex>
#include<bitset>
#include<random>
#include<complex>
#include<cassert>
#else
#include<bits/stdc++.h>
#ifdef ONLINE_JUDGE
#include<atcoder/all>
using namespace atcoder;
#else
#define gcd __gcd
#define lcm __detail::__lcm
#endif
#endif
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#ifdef LOCAL
//*
#include<atcoder/all>
using namespace atcoder;
//*/
unsigned popcount(unsigned x){
	return __popcnt(x);
}
unsigned popcountll(ull x){
	return __popcnt64(x);
}
unsigned parity(unsigned x){
	return popcount(x)%2;
}
unsigned parityll(ull x){
	return popcountll(x)%2;
}
unsigned clz(unsigned x){
	if(x==0)
		throw;
	unsigned cnt=__lzcnt(x);
	return cnt;
}
unsigned clzll(ull x){
	if(x==0)
		throw;
	unsigned cnt=__lzcnt64(x);
	return cnt;
}
unsigned ctz(unsigned x){
	if(x==0)
		throw;
	x&=~x+1;
	unsigned cnt=0;
	if(x&0xffff0000)
		cnt|=16;
	if(x&0xff00ff00)
		cnt|=8;
	if(x&0xf0f0f0f0)
		cnt|=4;
	if(x&0xcccccccc)
		cnt|=2;
	if(x&0xaaaaaaaa)
		cnt|=1;
	return cnt;
}
unsigned ctzll(ull x){
	if(x==0)
		throw;
	x&=~x+1;
	unsigned cnt=0;
	if(x&0xffffffff00000000)
		cnt|=32;
	if(x&0xffff0000ffff0000)
		cnt|=16;
	if(x&0xff00ff00ff00ff00)
		cnt|=8;
	if(x&0xf0f0f0f0f0f0f0f0)
		cnt|=4;
	if(x&0xcccccccccccccccc)
		cnt|=2;
	if(x&0xaaaaaaaaaaaaaaaa)
		cnt|=1;
	return cnt;
}
unsigned ffs(unsigned x){
	if(x==0)
		return 0;
	return ctz(x)+1;
}
unsigned ffsll(ull x){
	if(x==0)
		return 0;
	return ctzll(x)+1;
}
#define __builtin_popcount popcount
#define __builtin_popcountll popcountll
#define __builtin_parity parity
#define __builtin_parityll parityll
#define __builtin_clz clz
#define __builtin_clzll clzll
#define __builtin_ctz ctz
#define __builtin_ctzll ctzll
#define __builtin_ffs ffs
#define __builtin_ffsll ffsll
#endif
constexpr int mod=1e9+7;
constexpr int Mod=998244353;
constexpr int inf=mod;
constexpr ll linf=(ll)mod*mod;
struct fastio{
	fastio(){
		cin.tie(0);
		ios::sync_with_stdio(0);
		cout<<fixed<<setprecision(20);
	};
}fio;
template<class T>
bool chmax(T&a,const T&b){
	if(a<b){
		a=b;
		return 1;
	}
	return 0;
}
template<class T>
bool chmin(T&a,const T&b){
	if(a>b){
		a=b;
		return 1;
	}
	return 0;
}
typedef pair<int,int> P;
struct edge{int to,cost;};
vector<vector<edge>>G[2];
vector<int>dist;
int main(){
	int n,m;
	while(cin>>n>>m,n||m){
		G[0].assign(m,vector<edge>());
		G[1].assign(m,vector<edge>());
		int a,b,cost,time,k,p,q,r;
		for(int i=0;i<n;i++){
			cin>>a>>b>>cost>>time;
			a--,b--;
			G[0][a].emplace_back(edge{b,cost});
			G[0][b].emplace_back(edge{a,cost});
			G[1][a].emplace_back(edge{b,time});
			G[1][b].emplace_back(edge{a,time});
		}
		cin>>k;
		for(int i=0;i<k;i++){
			cin>>p>>q>>r;
			p--,q--;
			dist.assign(m,inf);
			priority_queue<P,vector<P>,greater<P>>que;
			dist[p]=0;
			que.emplace(0,p);
			while(!que.empty()){
				P p=que.top();
				que.pop();
				int v=p.second,d=p.first;
				if(d>dist[v])
					continue;
				for(auto x:G[r][v]){
					if(dist[x.to]>d+x.cost){
						dist[x.to]=d+x.cost;
						que.emplace(dist[x.to],x.to);
					}
				}
			}
			cout<<dist[q]<<endl;
		}
	}
}
accuracy: 1
time_ms: 90
memory_kb: 3544
final_rank: 14

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#define inf (1<<21)

using namespace std;

void WF(vector<vector<long>>&dc,vector<vector<long>>&dt,int m){
    for (int k=1;k<=m;k++)
       for(int i=1;i<=m;i++)
         for(int j=1;j<=m;j++){
           dc[i-1][j-1]=std::min(dc[i-1][j-1],dc[i-1][k-1]+dc[k-1][j-1]);
           dt[i-1][j-1]=std::min(dt[i-1][j-1],dt[i-1][k-1]+dt[k-1][j-1]);
         }
}

int main()
{
while(1){
   int n,m;
   scanf("%d %d",&n,&m);
   if(n==0 && m==0)return 0;
   
   vector<vector<long>>dc(m,vector<long>(m));
   vector<vector<long>>dt(m,vector<long>(m));
   
   for (int i=1;i<=m;i++){
       for(int j=1;j<=m;j++){
           dc[i-1][j-1]=inf;
           dt[i-1][j-1]=inf;
       }
   }
   
   for(int i=1;i<=m;i++){
      dc[i-1][i-1]=0;
      dt[i-1][i-1]=0;
   }
   int a,b,c,t;
   for(int i=0;i<n;i++){
      scanf("%d %d %d %d",&a,&b,&c,&t);
      dc[a-1][b-1]=dc[b-1][a-1]=c;
      dt[a-1][b-1]=dt[b-1][a-1]=t;
   }

   
   WF(dc,dt,m);
   int k,p,q,r;
   scanf("%d",&k);
   
   for(int i=0;i<k;i++){
      scanf("%d %d %d",&p,&q,&r);
      if(r==0)
         cout<<dc[p-1][q-1]<<endl;
      else
         cout<<dt[p-1][q-1]<<endl;
   }
}
   return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3648
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int INF = 100000;
int main(){
  while (true){
    int n, m;
    cin >> n >> m;
    if (n == 0 && m == 0){
      break;
    }
    vector<vector<int>> E1(m, vector<int>(m, INF));
    vector<vector<int>> E2(m, vector<int>(m, INF));
    for (int i = 0; i < m; i++){
      E1[i][i] = 0;
      E2[i][i] = 0;
    }
    for (int i = 0; i < n; i++){
      int a, b, c, t;
      cin >> a >> b >> c >> t;
      a--;
      b--;
      E1[a][b] = min(E1[a][b], c);
      E1[b][a] = min(E1[b][a], c);
      E2[a][b] = min(E2[a][b], t);
      E2[b][a] = min(E2[b][a], t);
    }
    for (int i = 0; i < m; i++){
      for (int j = 0; j < m; j++){
        for (int k = 0; k < m; k++){
          E1[j][k] = min(E1[j][k], E1[j][i] + E1[i][k]);
          E2[j][k] = min(E2[j][k], E2[j][i] + E2[i][k]);
        }
      }
    }
    int k;
    cin >> k;
    for (int i = 0; i < k; i++){
      int p, q, r;
      cin >> p >> q >> r;
      p--;
      q--;
      if (r == 0){
        cout << E1[p][q] << endl;
      }
      if (r == 1){
        cout << E2[p][q] << endl;
      }
    }
  }
}
accuracy: 1
time_ms: 40
memory_kb: 3416
final_rank: 4

code_snippet: #include<cstdio>
#include <queue>
#include <vector>

using namespace std;

struct edge{ int to,cost;};

int main(){
	int e,v,k;
	int a,b,c,t;
	int d[101];
	typedef pair<int,int> P;
	priority_queue<P,vector<P>,greater<P> > que;
	vector<edge> g[2][101];
	int s,last,type;
	
	while(1){
		scanf("%d %d",&e,&v);
		if(e==0&&v==0) break;
		for(int i=0;i<101;i++){
			g[0][i].clear();
			g[1][i].clear();
		}
		for(int i=0;i<e;i++){
			scanf("%d %d %d %d",&a,&b,&c,&t);
			g[0][a].push_back({b,c});
			g[1][a].push_back({b,t});
			g[0][b].push_back({a,c});
			g[1][b].push_back({a,t});
		}
		scanf("%d",&k);
		for(int kloop=0;kloop<k;kloop++){
			scanf("%d %d %d",&s,&last,&type);
			fill(d,d+v+1,30000000);
			d[s]=0;
			que.push(P(0,s));
			while(!que.empty()){
				//for(int i=1;i<=v;i++)printf("%d ,",d[i]);
				//printf("\n");
				P p = que.top();
				//printf("%d %d\n",p.first,p.second);
				que.pop();
				int ver = p.second;
				//printf("%d>=%d\n",d[ver],p.first);
				if(d[ver] < p.first) continue;
				for(int i=0;i<g[type][ver].size();i++){
					edge e = g[type][ver][i];
					//printf("%d->%d %d %d %d\n",ver,e.to,d[e.to] , d[ver],e.cost);
					if(d[e.to] > d[ver]+e.cost){
						d[e.to]=d[ver]+e.cost;
						que.push(P(d[e.to],e.to));
					}
				}
			}
			printf("%d\n",d[last]);
		}
	}
	return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 2772
final_rank: 1

code_snippet: #include<iostream>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<bitset>
#include<vector>
#include<string>
#include <iomanip>
#include <deque>
#include<list>
#include<cmath>
#define rep(i,n) for(int i=0;i<(n);i++)
using namespace std;
using ll=long long;
using P=pair<int,int>;
using P_S=pair<int,string>;
using P_D=pair<double,int>;
using T=tuple<int,int,char,ll,string>;

int main()
{
    int n,m;
    while(1){
    cin>>n>>m;
    if(n==0) break;
    vector<vector<vector<int>>> score(2,vector<vector<int>>(m,vector<int>(m,1<<29)));
    rep(i,m) score[0][i][i]=score[1][i][i]=0;
    rep(i,n){
        int a,b,c,t;
        cin>>a>>b>>c>>t;
        a--; b--;
        score[0][a][b]=score[0][b][a]=c;
        score[1][a][b]=score[1][b][a]=t;
    }
    rep(k,m){
        rep(i,m){
            rep(j,m){
                score[0][i][j]=min(score[0][i][j],score[0][i][k]+score[0][k][j]);
                score[1][i][j]=min(score[1][i][j],score[1][i][k]+score[1][k][j]);
            }
        }
    }
    int k;
    cin>>k;
    rep(i,k){
        int p,q,r;
        cin>>p>>q>>r;
        p--; q--;
        cout<<score[r][p][q]<<endl;
    }
    }
}
accuracy: 1
time_ms: 50
memory_kb: 3236
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define all(v) v.begin(), v.end()
#define rep(i, begin, end) for(auto i = (begin); i < (end); i++)
#define rrep(i, end, begin) for(auto i = (end) - 1; i >= (begin); i--)
template<class T> inline bool chmin(T& a, T b){ if (a > b){ a = b; return true; } return false; }
template<class T> inline bool chmax(T& a, T b){ if (a < b){ a = b; return true; } return false; }
template<class T> inline T roundup(T a, T b){ return (a + b - 1) / b; }
constexpr int dy[] = {0, 1, 0, -1, 1, 1, -1, -1, 0};
constexpr int dx[] = {1, 0, -1, 0, 1, -1, 1, -1, 0};
using ll = long long;
using ull = unsigned long long;
constexpr ll INF = 1e9;
constexpr ll MOD = 1e9 + 7;
struct Edge{ int to; ll cost; Edge(int to, ll cost) : to(to), cost(cost) {} };
using Graph = vector<vector<Edge>>;

vector<ll> dijkstra(const Graph &g, int s){
    int n = g.size();
    vector<ll> dist(n, INF * INF);
    dist[s] = 0;
    priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> q;
    q.emplace(dist[s], s);
    while(q.size()){
        pair<ll, int> p = q.top(); q.pop();
        int v = p.second;
        if(dist[v] < p.first) continue;
        for(auto e : g[v]){
            if(chmin(dist[e.to], dist[v] + e.cost)) q.emplace(dist[e.to], e.to);
        }
    }
    return dist;
}

void solve(){
    int n, m;
    cin >> m >> n;
    if(n == 0 && m == 0) exit(0);
    Graph g(n), h(n);
    rep(_, 0, m){
        int a, b, cost, time;
        cin >> a >> b >> cost >> time;
        a--, b--;
        g[a].emplace_back(b, time);
        g[b].emplace_back(a, time);
        h[a].emplace_back(b, cost);
        h[b].emplace_back(a, cost);
    }
    int k;
    cin >> k;
    
    vector<vector<ll>> dist(n), cost(n);
    rep(i, 0, n) dist[i] = dijkstra(g, i), cost[i] = dijkstra(h, i);
    while(k--){
        int p, q, r;
        cin >> p >> q >> r;
        p--, q--;
        if(r == 1) cout << dist[p][q] << endl;
        else cout << cost[p][q] << endl;
    }
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    
    while(true) solve();
}
accuracy: 1
time_ms: 100
memory_kb: 3900
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long long MOD1 = 1000000007;
const long long MOD2 = 998244353;
typedef long long ll;
typedef pair<long long, long long> P;
const long long INF = 1e9;
template <typename T>
void input_arr(vector<T>& A, long long N) {
    for (long long i = 0; i < N; i++) {
        cin >> A[i];
    }
}
int main() {
    long long N, M; cin >> N >> M;
    while (N != 0) {
        vector<vector<long long>>G(M, vector<long long>(M, INF)), G2(M, vector<long long>(M, INF));
        for (long long i = 0; i < N; i++) {
            long long u, v; cin >> u >> v;
            long long cost1 , cost2; cin >> cost1 >> cost2;
            u--; v--;
            G[u][v] = G[v][u] = cost1;
            G2[u][v] = G2[v][u] = cost2;
        }
        for (long long i = 0; i < M; i++) {
            G[i][i] = 0;
            G2[i][i] = 0;
        }
        for (long long k = 0; k < M; k++) {
            for (long long i = 0; i < M; i++) {
                for (long long j = 0; j < M; j++) {
                    G[i][j] = min(G[i][j], G[i][k] + G[k][j]);
                	G2[i][j] = min(G2[i][j], G2[i][k] + G2[k][j]);
                }
            }
        }
        long long Q; cin >> Q;
        for (long long i = 0; i < Q; i++) {
            long long u, v, q; cin >> u >> v >> q;
            u--; v--;
            if (q) {
                cout << G2[u][v] << endl;
            }
            else cout << G[u][v] << endl;
        }
        cin >> N >> M;
    }
}
accuracy: 1
time_ms: 40
memory_kb: 3552
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;

int main(){
  for(;;){
    long long int INF = 1000000000000000000;
    int N,M;
    cin >> N >> M;
    if(N == 0 && M == 0) break;
    vector<vector<long long int> > costd(M,vector<long long int>(M,INF));
    vector<vector<long long int> > timed(M,vector<long long int>(M,INF));
    for(int i=0;i<M;i++){
      costd[i][i] = 0;
      timed[i][i] = 0;
    }
    for(int i=0;i<N;i++){
      int a,b;
      long long int cost,time;
      cin >> a >> b >> cost >> time;
      a--;
      b--;
      costd[a][b] = min(costd[a][b],cost);
      costd[b][a] = min(costd[b][a],cost);
      timed[a][b] = min(timed[a][b],time);
      timed[b][a] = min(timed[b][a],time);
    }
    for(int k=0;k<M;k++) for(int i=0;i<M;i++) for(int j=0;j<M;j++) costd[i][j] = min(costd[i][j],costd[i][k]+costd[k][j]);
    for(int k=0;k<M;k++) for(int i=0;i<M;i++) for(int j=0;j<M;j++) timed[i][j] = min(timed[i][j],timed[i][k]+timed[k][j]);
    int K;
    cin >> K;
    for(int i=0;i<K;i++){
      int p,q,r;
      cin >> p >> q >> r;
      if(r == 0) cout << costd[p-1][q-1] << endl;
      else cout << timed[p-1][q-1] << endl;
    }
  }
}
accuracy: 1
time_ms: 50
memory_kb: 3236
final_rank: 2

code_snippet: #include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<list>
#include<algorithm>
#include<numeric>
#include<cmath>
#include<iomanip>
#include<regex>
#include<random>
using namespace std;
#define int long long
#define uint unsigned long long
const int mod=1e9+7;
const int inf=mod*mod;
const double eps=1e-9;
typedef pair<int,int> P;
struct edge{int to,cost;};
vector<edge>G[2][1000];
int dist[1000];
signed main(){
	int n,m;
	while(cin>>n>>m,n||m){
		for(int i=0;i<m;i++){
			G[0][i].clear();
			G[1][i].clear();
		}
		int a,b,cost,time,k,p,q,r;
		for(int i=0;i<n;i++){
			cin>>a>>b>>cost>>time;
			a--,b--;
			G[0][a].emplace_back(edge{b,cost});
			G[0][b].emplace_back(edge{a,cost});
			G[1][a].emplace_back(edge{b,time});
			G[1][b].emplace_back(edge{a,time});
		}
		cin>>k;
		for(int i=0;i<k;i++){
			cin>>p>>q>>r;
			p--,q--;
			for(int j=0;j<m;j++)
				dist[j]=inf;
			priority_queue<P,vector<P>,greater<P>>que;
			dist[p]=0;
			que.emplace(0,p);
			while(!que.empty()){
				P p=que.top();
				que.pop();
				int v=p.second,d=p.first;
				if(d>dist[v])
					continue;
				for(auto x:G[r][v]){
					if(dist[x.to]>d+x.cost){
						dist[x.to]=d+x.cost;
						que.emplace(dist[x.to],x.to);
					}
				}
			}
			cout<<dist[q]<<endl;
		}
	}
}
accuracy: 1
time_ms: 120
memory_kb: 3284
final_rank: 5

code_snippet: #include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<list>
#include<algorithm>
#include<numeric>
#include<cmath>
#include<iomanip>
#include<regex>
#include<random>
using namespace std;
#define int long long
#define uint unsigned long long
const int mod=1e9+7;
const int inf=mod*mod;
const double eps=1e-9;
typedef pair<int,int> P;
struct edge{int to,cost;};
vector<edge>G[2][1000];
int dist[1000];
signed main(){
	int n,m;
	while(cin>>n>>m,n||m){
		for(int i=0;i<m;i++){
			G[0][i].clear();
			G[1][i].clear();
		}
		int a,b,cost,time,k,p,q,r;
		for(int i=0;i<n;i++){
			cin>>a>>b>>cost>>time;
			a--,b--;
			G[0][a].emplace_back(edge{b,cost});
			G[0][b].emplace_back(edge{a,cost});
			G[1][a].emplace_back(edge{b,time});
			G[1][b].emplace_back(edge{a,time});
		}
		cin>>k;
		for(int i=0;i<k;i++){
			cin>>p>>q>>r;
			p--,q--;
			for(int j=0;j<m;j++)
				dist[j]=inf;
			priority_queue<P,vector<P>,greater<P>>que;
			dist[p]=0;
			que.emplace(0,p);
			while(!que.empty()){
				P p=que.top();
				que.pop();
				int v=p.second,d=p.first;
				if(d>dist[v])
					continue;
				for(auto x:G[r][v]){
					if(dist[x.to]>d+x.cost){
						dist[x.to]=d+x.cost;
						que.emplace(dist[x.to],x.to);
					}
				}
			}
			cout<<dist[q]<<endl;
		}
	}
}
accuracy: 1
time_ms: 100
memory_kb: 3628
final_rank: 16

code_snippet: #include <bits/stdc++.h>
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define drep(i,j,n) for(int i=0;i<(int)(n-1);i++)for(int j=i+1;j<(int)(n);j++)
#define trep(i,j,k,n) for(int i=0;i<(int)(n-2);i++)for(int j=i+1;j<(int)(n-1);j++)for(int k=j+1;k<(int)(n);k++)
#define codefor int test;scanf("%d",&test);while(test--)
#define INT(...) int __VA_ARGS__;in(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;in(__VA_ARGS__)
#define yes(ans) if(ans)printf("yes\n");else printf("no\n")
#define Yes(ans) if(ans)printf("Yes\n");else printf("No\n")
#define YES(ans) if(ans)printf("YES\n");else printf("NO\n")
#define popcount(v) __builtin_popcount(v)
#define vector2d(type,name,h,...) vector<vector<type>>name(h,vector<type>(__VA_ARGS__))
#define vector3d(type,name,h,w,...) vector<vector<vector<type>>>name(h,vector<vector<type>>(w,vector<type>(__VA_ARGS__)))
#define umap unordered_map
#define uset unordered_set
using namespace std;
using ll = long long;
const int MOD=1000000007;
const int MOD2=998244353;
const int INF=1<<30;
const ll INF2=1LL<<60;
//入力系
void scan(int& a){scanf("%d",&a);}
void scan(long long& a){scanf("%lld",&a);}
template<class T,class L>void scan(pair<T, L>& p){scan(p.first);scan(p.second);}
template<class T,class U,class V>void scan(tuple<T,U,V>& p){scan(get<0>(p));scan(get<1>(p));scan(get<2>(p));}
template<class T> void scan(T& a){cin>>a;}
template<class T> void scan(vector<T>& vec){for(auto&& it:vec)scan(it);}
void in(){}
template <class Head, class... Tail> void in(Head& head, Tail&... tail){scan(head);in(tail...);}
//出力系
void print(const int& a){printf("%d",a);}
void print(const long long& a){printf("%lld",a);}
void print(const double& a){printf("%.15lf",a);}
template<class T,class L>void print(const pair<T, L>& p){print(p.first);putchar(' ');print(p.second);}
template<class T> void print(const T& a){cout<<a;}
template<class T> void print(const vector<T>& vec){if(vec.empty())return;print(vec[0]);for(auto it=vec.begin();++it!= vec.end();){putchar(' ');print(*it);}}
void out(){putchar('\n');}
template<class T> void out(const T& t){print(t);putchar('\n');}
template <class Head, class... Tail> void out(const Head& head,const Tail&... tail){print(head);putchar(' ');out(tail...);}
//デバッグ系
template<class T> void dprint(const T& a){cerr<<a;}
template<class T> void dprint(const vector<T>& vec){if(vec.empty())return;cerr<<vec[0];for(auto it=vec.begin();++it!= vec.end();){cerr<<" "<<*it;}}
void debug(){cerr<<endl;}
template<class T> void debug(const T& t){dprint(t);cerr<<endl;}
template <class Head, class... Tail> void debug(const Head& head, const Tail&... tail){dprint(head);cerr<<" ";debug(tail...);}
ll intpow(ll a, ll b){ ll ans = 1; while(b){ if(b & 1) ans *= a; a *= a; b /= 2; } return ans; }
ll modpow(ll a, ll b, ll p){ ll ans = 1; while(b){ if(b & 1) (ans *= a) %= p; (a *= a) %= p; b /= 2; } return ans; }
ll modinv(ll a, ll m) {ll b = m, u = 1, v = 0;while (b) {ll t = a / b;a -= t * b; swap(a, b);u -= t * v; swap(u, v);}u %= m;if (u < 0) u += m;return u;}
ll updivide(ll a,ll b){return (a+b-1)/b;}
template<class T> void chmax(T &a,const T b){if(b>a)a=b;}
template<class T> void chmin(T &a,const T b){if(b<a)a=b;}

//負の閉路がない場合はtrue，負の閉路がある場合はfalseを返す
bool warshallFloyd(vector<vector<ll>> &A){
    int n=A.size();
    for(int k=0;k<n;k++){
        for(int i=0;i<n;i++){
            if(A[i][k]==INF2)continue;
            for(int j=0;j<n;j++){
                if(A[k][j]==INF2)continue;
                A[i][j]=min(A[i][j],A[i][k]+A[k][j]);
            }
        }
    }
    for(int i=0;i<n;i++){
        //ある点から連結であるという条件を加える場合A[u][v]!=INF2のようにする
        if(A[i][i]<0)return false;
    }
    return true;
}

int main(){
    while(1){
        INT(n,m);
        if(n==0&&m==0)return 0;
        vector2d(ll,A,m,m,INF2);
        vector2d(ll,B,m,m,INF2);
        int u,v,c,t;
        rep(i,n){
            in(u,v,c,t);
            A[--u][--v]=c;
            A[v][u]=c;
            B[u][v]=t;
            B[v][u]=t;
        }
        rep(i,m)A[i][i]=B[i][i]=0;
        warshallFloyd(A);
        warshallFloyd(B);
        codefor{
            in(u,v,c);
            if(c==0)out(A[--u][--v]);
            else out(B[--u][--v]);
        }
    }
}
accuracy: 1
time_ms: 30
memory_kb: 3620
final_rank: 12