Problem:
Railway Connection
Tokyo has a very complex railway system.
For example, there exists a partial map of lines and stations
as shown in Figure D-1.
Figure D-1: A sample railway network
Suppose you are going to station D from station A.
Obviously, the path with the shortest distance is A→B→D.
However, the path with the shortest distance does not necessarily
mean the minimum cost.
Assume the lines A-B, B-C, and C-D are operated by one railway company,
and the line B-D is operated by another company.
In this case, the path A→B→C→D may cost less than A→B→D.
One of the reasons is that the fare is not proportional to the distance.
Usually, the longer the distance is, the fare per unit distance is lower.
If one uses lines of more than one railway company,
the fares charged by these companies are simply added together,
and consequently the total cost may become higher although the distance is shorter
than the path using lines of only one company.
In this problem, a railway network including multiple railway companies is given.
The fare table (the rule to calculate the fare from the distance) of each company is also given.
Your task is, given the starting point and the goal point, to write a program
that computes the path with the least total fare.
Input
The input consists of multiple datasets, each in the following format.
n
m
c
s
g
x
1
y
1
d
1
c
1
...
x
m
y
m
d
m
c
m
p
1
...
p
c
q
1,1
...
q
1,
p
1
-1
r
1,1
...
r
1,
p
1
...
q
c
,1
...
q
c,p
c
-1
r
c
,1
...
r
c,p
c
Every input item in a dataset is a non-negative integer.
Input items in the same input line are separated by a space.
The first input line gives the size of the railway network and the intended trip.
n
is the number of stations (2 ≤
n
≤ 100).
m
is the number of lines connecting two stations (0 ≤
m
≤ 10000).
c
is the number of railway companies (1 ≤
c
≤ 20).
s
is the station index of the starting point (1 ≤
s
≤
n
).
g
is the station index of the goal point (1 ≤
g
≤
n
,
g
≠
s
).
The following
m
input lines give the details of (railway) lines.
The
i
-th line connects two stations
x
i
and
y
i
(1 ≤
x
i
≤
n
,
1 ≤
y
i
≤
n
,
x
i
≠
y
i
).
Each line can be traveled in both directions.
There may be two or more lines connecting the same pair of stations.
d
i
is the distance of the
i
-th line (1 ≤
d
i
≤ 200).
c
i
is the company index of the railway company operating the line (1 ≤
c
i
≤
c
).
The fare table (the relation between the distance and the fare)
of each railway company can be expressed as a line chart.
For the railway company
j
,
the number of sections of the line chart is given by
p
j
(1 ≤
p
j
≤ 50).
q
j,k
(1 ≤
k
≤
p
j
-1) gives
the distance separating two sections of the chart
(1 ≤
q
j,k
≤ 10000).
r
j,k
(1 ≤
k
≤
p
j
) gives
the fare increment per unit distance for the corresponding section of the chart
(1 ≤
r
j,k
≤ 100).
More precisely, with the fare for the distance
z
denoted by
f
j
(
z
),
the fare for distance
z
satisfying
q
j
,
k
-1
+1 ≤
z
≤
q
j
,
k
is computed by the recurrence relation
f
j
(
z

...(truncated)

Submitted solutions:

code_snippet: /*
 * Author:heroming
 * File:heroming.cpp
 * Time:2012-7-19 9:33:45
 */
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;

#define SZ(v) ((int)(v).size())
const int INFI = 1<<30;
const int MAXN = 102, MAXC = 22, MAXP = 52;

bool inQ[MAXN];
int n, m, c, s, g;
int maps[MAXN][MAXN][MAXC], dis[MAXN];
int P[MAXC], Q[MAXP][MAXP], R[MAXP][MAXP];

int get_cost(int k, int d)
{
        int x = 0;
        for (int i = 1; i < P[k]; ++ i)
        {
                if (d > Q[k][i])
                        x += (Q[k][i] - Q[k][i - 1]) * R[k][i];
                else
                {
                        x += (d - Q[k][i - 1]) * R[k][i];
                        return x;
                }
        }
        return x + R[k][P[k]] * (d - Q[k][P[k] - 1]);
}

void SPFA()
{
        memset(inQ, 0, sizeof(inQ));
        for (int i = 1; i <= n; ++ i)
                dis[i] = INFI;
        dis[s] = 0;
        queue<int> Q;
        Q.push(s);
        inQ[s] = 1;
        while (! Q.empty())
        {
                int u = Q.front();
                Q.pop();
                inQ[u] = 0;
                for (int i = 1; i <= n; ++ i)
                        for (int j = 1; j <= c; ++ j)
                                if (maps[u][i][j] != -1)
                                {
                                        int p = get_cost(j, maps[u][i][j]);
                                        if (dis[u] + p < dis[i])
                                        {
                                                dis[i] = dis[u] + p;
                                                if (! inQ[i])
                                                {
                                                        Q.push(i);
                                                        inQ[i] = 1;
                                                }
                                        }
                                }
        }
}

int main()
{
        while (scanf("%d%d%d%d%d", &n, &m, &c, &s, &g) != EOF && n)
        {
                memset(maps, -1, sizeof(maps));
                int x, y, w, e;
                for (int i = 0; i < m; ++ i)
                {
                        scanf("%d%d%d%d", &x, &y, &w, &e);
                        if (maps[x][y][e] != -1)
                                maps[x][y][e] = maps[y][x][e] = min(maps[x][y][e], w);
                        else
                                maps[x][y][e] = maps[y][x][e] = w;
                }
                for (int i = 1; i <= c; ++ i)
                        scanf("%d", &P[i]);
                for (int i = 1; i <= c; ++ i)
                {
                        for (int j = 1; j < P[i]; ++ j)
                                scanf("%d", &Q[i][j]);
                        for (int j = 1; j <= P[i]; ++ j)
                                scanf("%d", &R[i][j]);
                }
                for (int l = 1; l <= c; ++ l)
                        for (int k = 1; k <= n; ++ k)
                                for (int i = 1; i <= n; ++ i)
                                        for (int j = 1; j <= n; ++ j)
                                        {
                                                if (i == j || i == k || j == k || maps[i][k][l] == -1 || maps[k][j][l] == -1)
                                                        continue;
                                                if (maps[i][j][l] == -1 || maps[i][k][l] + maps[k][j][l] < maps[i][j][l])
                                                        maps[i][j][l] = maps[j][i][l] = maps[i][k][l] + maps[k][j][l];
                                        }

                SPFA();
                if (dis[g] == INFI)
                        printf("-1\n");
                else
                        printf("%d\n", dis[g]);
        }
        return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 4336
final_rank: 10

code_snippet: #include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

#define mpair make_pair
#define pii pair<int,int>
#define MM(a,b) memset(a,b,sizeof(a));
typedef long long lld;
typedef unsigned long long u64;
template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;}
template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;}
#define maxn 105
const int inf = 1000000000;

int n,m,c;

struct Edge{
    int x,y,d,ci;
    void init(){
        scanf("%d%d%d%d", &x,&y,&d,&ci);
    }
}e[10010];
struct Info{
    int p[53], r[53];
    void init(){
        for(int i=1;i<p[0];++i) scanf("%d", p+i);
        for(int i=1;i<=p[0];++i) scanf("%d", r+i);
    }
}info[25];

int g[maxn][maxn];
int endmap[maxn][maxn];
int dis[maxn][maxn];


int cal(int d,int ci){
    Info *h= &info[ci];
    if( h->p[0] == 1 || d<= h->p[1] ) return d* h->r[1];
    int i=1,cost= h->p[1] * h->r[1];
    while(1){
        if( (h->p[i] < d && d<= h->p[i+1]) || i== h->p[0]-1 ){
            cost += ( d - h->p[i] ) * h->r[i+1];
            break;
        }
        else cost += (h->p[i+1]-h->p[i]) * h->r[i+1];
        ++i;
    }
    return cost;
}

void floyd(){
    for(int k=1;k<=n;++k)
        for(int i=1;i<=n;++i)
            if( i!=k && g[i][k]!=inf )
                for(int j=1;j<=n;++j)
                    if( j!=i && j!=k && g[k][j]!=inf )
                        up_min( g[i][j], g[i][k] + g[k][j] );
}

int main()
{
    //freopen("D.in","r",stdin);
    int st,ed;
    while( cin>>n>>m>>c>>st>>ed, n+m+c+st+ed ){
        for(int i=0;i<m;++i) e[i].init();
        for(int i=1;i<=c;++i) scanf("%d", &info[i].p[0] );
        for(int i=1;i<=c;++i) info[i].init();

        for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)endmap[i][j]= inf;

        for(int ci= 1; ci<=c; ++ci){
            for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)g[i][j]= inf;
            for(int i=0;i<m;++i){
                if( e[i].ci == ci ){
                    if( up_min( g[e[i].x][e[i].y], e[i].d ) )
                        g[ e[i].y ][ e[i].x ]= e[i].d;
                }
            }
            floyd();

            for(int i=1;i<=n;++i)
                for(int j=1;j<=n;++j)
                    if( i!=j && g[i][j]!=inf ){
                        int t= cal( g[i][j], ci );
                        if( up_min( endmap[i][j], t ) )
                            endmap[j][i]= t;
                    }
        }
        for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)g[i][j]= endmap[i][j];
        floyd();
        if( g[st][ed] == inf ) puts("-1");
        else printf("%d\n", g[st][ed]);
    }
}
accuracy: 1
time_ms: 40
memory_kb: 3712
final_rank: 1

code_snippet: #include <queue>
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#ifndef ONLINE_JUDGE
#define _GLIBCXX_DEBUG // 配列外参照のエラー
#endif

// スタンダードライブラリ
#include <bits/stdc++.h>
using namespace std;

// 型関連
using ll = long long;
using lint = long long;
using pll = pair<ll, ll>;
using plll = tuple<ll, ll, ll>;
using pii = pair<int, int>;
using piii = tuple<ll, ll, ll>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vvvvi = vector<vector<vector<vector<int>>>>;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
using vvvl = vector<vector<vector<ll>>>;
using vvvvl = vector<vector<vector<vector<ll>>>>;

template <class T> using prique = priority_queue<T>;

// 型定数
constexpr ll mod = 998244353;
constexpr ll MOD = 1000000007;
int INF32 = 1e9;
ll INF64 = 9e18;
#define endl '\n';

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

/////////////////////////// print関連
template <typename T> void print(vector<T> A);
void print();
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail);
void print(string S);
template <typename T> void print(vector<vector<T>> &F);

inline void Yes(bool f);

///////////////////ここから//////////////////////
bool solve() {
    int N, M, C, s, g;
    cin >> N >> M >> C >> s >> g;
    if (N == 0) {
        return false;
    }
    s--;
    g--;
    vvvi CE(C, vvi(N, vi(N, INF32)));

    for (int i = 0; i < M; i++) {
        int u, v, d, c;
        cin >> u >> v >> d >> c;
        u--, v--, c--;
        CE[c][u][v] = min(CE[c][u][v], d);
        CE[c][v][u] = min(CE[c][v][u], d);
    }

    int max_size = N * 200;
    vvl Ryokin(C);
    vector<int> P(C);
    for (int i = 0; i < C; i++) {
        cin >> P[i];
    }
    for (int i = 0; i < C; i++) {
        vector<ll> Q(P[i], 0);
        for (int j = 0; j < P[i]-1; j++) {
            cin >> Q[j + 1];
        }
        Q.push_back(max_size);
        vector<ll> R(P[i]);
        for (int j = 0; j < P[i]; j++) {
            cin >> R[j];
        }

        Ryokin[i].push_back(0);
        for (int j = 1; j < Q.size(); j++) {
            for (int k = Q[j - 1]; k < Q[j]; k++) {
                Ryokin[i].emplace_back(Ryokin[i].back() + R[j-1]);
            }
        }
        //print(Ryokin[i]);
    }

    vector<vector<pll>> G(N);
    for (int c = 0; c < C; c++) {
        for (int k = 0; k < N; k++) {
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    CE[c][i][j] = min(CE[c][i][j], CE[c][i][k] + CE[c][k][j]);
                }
            }
        }
        for (int i = 0; i < N; i++) {
            for (int j = i + 1; j < N; j++) {
                ll D = CE[c][i][j];
                if (D == INF32) {
                    continue;
                }

                ll cost = Ryokin[c][D];
                G[i].emplace_back(j, cost);
                G[j].emplace_back(i, cost);
            }
        }
    }

    vector<ll> dist(N, INF64);
    vector<int> f(N, 0);
    priority_queue<pll, vector<pll>, greater<pll>> que;
    que.emplace(0, s);
    dist[s]=0;
    while (!que.empty()) {
        auto [D, v] = que.top();
        que.pop();
        if (f[v]) {
            continue;
        }
        f[v] = 1;
        for (auto [nv, cost] : G[v]) {
            if (dist[nv] > dist[v] + cost) {
                dist[nv] = dist[v] + cost;
                que.emplace(dist[nv],nv);
            }
        }
    }
    if (dist[g] == INF64) {
        print(-1);
    } else {
        print(dist[g]);
    }
    


    return true;
}

int main() {
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    while (solve())
        ;
}

////////////////////print/////////////////////////
// 1次元ベクトルを出力する
template <typename T> void print(vector<T> A) {
    if (A.size() == 0) {
        return;
    }
    for (size_t i = 0; i < A.size() - 1; i++) {
        cout << A[i] << ' ';
    }
    cout << A[A.size() - 1] << endl;
    return;
}

// 2次元ベクトルを出力する
template <typename T> void print(vector<vector<T>> &F) {
    for (size_t i = 0; i < F.size(); i++) {
        for (size_t j = 0; j < F[i].size(); j++) {
            cout << F[i][j];
            if (j < F[i].size() - 1) {
                cout << ' ';
            }
        }
        cout << endl;
    }
}

// 空白行を出力するprint
void print() { cout << endl; }

// 数値・文字列を空白区切りで出力する. print(a,b)など
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    cout << head;
    if (sizeof...(tail) != 0)
        cout << " ";
    print(forward<Tail>(tail)...);
}

void print(string S) { cout << S << endl; }

//////////////出力関連

inline void Yes(bool f) {
    if (f) {
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
}
accuracy: 1
time_ms: 70
memory_kb: 11080
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int INF = 1e9 + 7;
int main(){
    while(true){
      int n,m,c,s,g;
      cin >> n >> m >> c >> s >> g;
      if(n == 0) break;
        s--;
        g--;
        vector<vector<vector<int>>>Dist(n,vector<vector<int>>(n,vector<int>(c,INF)));

        for(int i = 0;i < m;i++){
          int x,y,d,com;
            cin >> x >> y >> d >> com;
            x--;
            y--;
            com--;
            if(Dist[x][y][com] > d){
                Dist[x][y][com] = d;
                Dist[y][x][com] = d;
            }
        }
        
        vector<int>p(c);
        for(int i = 0;i < c;i++) cin >> p[i];
        
        
  for (int i = 0;i < c;i++){
    for (int j = 0;j < n;j++){
        for (int k = 0;k < n;k++){
            for (int k2 = 0;k2 < n;k2++){
                if (Dist[k][k2][i] > Dist[k][j][i] + Dist[j][k2][i]){
                    Dist[k][k2][i] = Dist[k][j][i] + Dist[j][k2][i];
                }
            }
        }
    }

    
    if (p[i] == 0) continue;

    vector<int>q(p[i]-1);
    vector<int>r(p[i]);
    vector<int>C(100000, 0);

    for (int j = 0;j < p[i]-1;j++) cin >> q[j];
    for (int j = 0;j < p[i];j++) cin >> r[j];

    int cnt = 0;
    for (int j = 1;j < 100000;j++){
        if (cnt<p[i]-1 && j>q[cnt]) cnt++;
        C[j] = C[j - 1]+r[cnt];
    }

    for (int k = 0;k < n;k++) {
        for (int k2 = 0;k2 < n;k2++) {
            if (Dist[k][k2][i] < INF) {
                if (Dist[k][k2][i] < 100000) {
                    Dist[k][k2][i] = C[Dist[k][k2][i]];
                } 
                else {
                    Dist[k][k2][i] = INF;
                }
            }
        }
    }
}

 vector<vector<int>>vec(n,vector<int>(n,INF));
        for(int i = 0; i < n; i++){
          vec[i][i] = 0;
        for(int j = 0; j < n; j++){
          for(int k = 0; k < c; k++){
            if(vec[i][j] > Dist[i][j][k]){
                vec[i][j] = Dist[i][j][k];
             }
           }
         }
        }
        
        for(int i = 0; i < n; i++){
          for(int j = 0; j < n; j++){
            for(int k = 0; k < n; k++){
            if(vec[j][k] > vec[j][i] + vec[i][k]){
                vec[j][k] = vec[j][i] + vec[i][k];
              }
            }
         }
        }
        
        if(vec[s][g] < INF){
          cout << vec[s][g] << endl;
         }
    else{
    cout << -1 << endl;
    }

       
    }
}
accuracy: 1
time_ms: 230
memory_kb: 4736
final_rank: 14

code_snippet: #include <vector>
#include <iostream>
using namespace std;

int main(){
    int n, m, c, s, g, x, y, ca, d, p;
    while(cin >> n >> m >> c >> s >> g && n != 0){
        s--;
        g--;
        vector< vector< vector <int> > > D(n, vector<vector<int> >(n, vector<int>(c, 10000000)));

        for(int i = 0; i < m; i++){
            cin >> x >> y >> d >> ca;
            x--; y--; ca--;
            if(D.at(x).at(y).at(ca) > d){
                D.at(x).at(y).at(ca) = d;
                D.at(y).at(x).at(ca) = d;
            }
        }

        vector<int> P(c);
        for(int i = 0; i < c; i++){
            cin >> P.at(i);
        }

        for(int l = 0; l < c; l++){
            // Warshall-Floyd
            for(int k = 0; k < n; k++){
                for(int i = 0; i < n; i++){
                    for(int j = 0; j < n; j++){
                        if(D.at(i).at(j).at(l) > D.at(i).at(k).at(l) + D.at(k).at(j).at(l)){
                            D.at(i).at(j).at(l) = D.at(i).at(k).at(l) + D.at(k).at(j).at(l);
                        }
                    }
                }
            }

            p = P.at(l);
            if (p == 0) continue;  // 料金情報がない会社はスキップ

            vector<int> Q(p - 1);
            vector<int> R(p);
            vector<int> C(20000, 0);

            for(int i = 0; i < p - 1; i++){
                cin >> Q.at(i);
            }
            for(int i = 0; i < p; i++){
                cin >> R.at(i);
            }

            int z = 0;
            for(int i = 1; i < 20000; i++){
                if(z < p - 1 && i > Q.at(z)){
                    z++;
                }
                C.at(i) = C.at(i - 1) + R.at(z);
            }

            for(int i = 0; i < n; i++){
                for(int j = 0; j < n; j++){
                    if(D.at(i).at(j).at(l) < 10000000){
                        int dist = D.at(i).at(j).at(l);
                        if (dist < 20000) {
                            D.at(i).at(j).at(l) = C.at(dist);
                        } else {
                            D.at(i).at(j).at(l) = 10000000;  // 無効距離は無限コストに
                        }
                    }
                }
            }
        }

        vector<vector<int>> A(n, vector<int>(n, 10000000));
        for(int i = 0; i < n; i++){
            A.at(i).at(i) = 0;
            for(int j = 0; j < n; j++){
                for(int k = 0; k < c; k++){
                    if(A.at(i).at(j) > D.at(i).at(j).at(k)){
                        A.at(i).at(j) = D.at(i).at(j).at(k);
                    }
                }
            }
        }

        for(int k = 0; k < n; k++){
            for(int i = 0; i < n; i++){
                for(int j = 0; j < n; j++){
                    if(A.at(i).at(j) > A.at(i).at(k) + A.at(k).at(j)){
                        A.at(i).at(j) = A.at(i).at(k) + A.at(k).at(j);
                    }
                }
            }
        }

        if(A.at(s).at(g) < 10000000){
            cout << A.at(s).at(g) << endl;
        } else {
            cout << "-1" << endl;
        }
    }
}
accuracy: 1
time_ms: 360
memory_kb: 4444
final_rank: 16

code_snippet: #include <vector>
#include <iostream> 

using namespace std;

int main(){
    int n,m,c,s,g,x,y,ca,d,p;
    while(cin>>n>>m>>c>>s>>g && n!=0){
        s--;
        g--;
        vector< vector< vector <int> > > D (n,vector<vector<int> >(n,vector<int>(c, 10000000)));
        for(int i=0; i<m; i++){
            cin>>x>>y>>d>>ca;
            if(D.at(x-1).at(y-1).at(ca-1)>d){
                D.at(x-1).at(y-1).at(ca-1)=d;
                D.at(y-1).at(x-1).at(ca-1)=d;
            }
        }
        vector<int> P(c);
        for(int i=0; i<c; i++){
            cin>>P.at(i);
        }
        for(int l=0; l<c; l++){
            for(int k=0; k<n; k++){
                for(int i=0;i<n;i++){
                    for(int j=0; j<i;j++){
                        if(D.at(i).at(j).at(l)>(D.at(i).at(k).at(l)+D.at(k).at(j).at(l))){
                            D.at(i).at(j).at(l)=(D.at(i).at(k).at(l)+D.at(k).at(j).at(l));
                            D.at(j).at(i).at(l)=D.at(i).at(j).at(l);
                        }
                    }
                }
            }
            p=P.at(l);
            vector<int> Q(p);
            vector<int> R(p);
            vector<int> C(20000,0);
            for(int i=0; i<p-1; i++){
                cin>>Q.at(i);
            }
            for(int i=0; i<p; i++){
                cin>>R.at(i);
            }
            int z=0;
            for(int i=1; i<20000; i++){
                if(z!=p-1 && i>Q.at(z)){
                    z++;
                }
                C.at(i)=C.at(i-1)+R.at(z);
            }
            for(int i=0;i<n;i++){
                for(int j=0; j<n;j++){
                    if(D.at(i).at(j).at(l)<10000000){
                        int dist=D.at(i).at(j).at(l);
                        D.at(i).at(j).at(l)=C.at(dist);
                    }
                }
            }
        }
        vector<vector<int> >A(n,vector<int>(n,10000000));
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                for(int k=0; k<c; k++){
                    if(A.at(i).at(j)>D.at(i).at(j).at(k)){
                        A.at(i).at(j) = D.at(i).at(j).at(k);
                    }
                }
            }
        }
        for(int k=0; k<n; k++){
            for(int i=0;i<n;i++){
             for(int j=0; j<n;j++){
                    if(A.at(i).at(j)>(A.at(i).at(k)+A.at(k).at(j))){
                       A.at(i).at(j)=(A.at(i).at(k)+A.at(k).at(j));
                    }
                }
            }
        }
        if(A.at(s).at(g)<10000000){
            cout<<A.at(s).at(g)<<endl;
        }
        else{
            cout<<"-1"<<endl;
        }
    }
}
accuracy: 1
time_ms: 190
memory_kb: 4520
final_rank: 9

code_snippet: #include <cstdio>
#include <queue>
#include <tuple>
#include <vector>
#define repeat(i, n) for (int i = 0; (i) < int(n); ++(i))
using namespace std;
template <class T> inline void setmax(T & a, T const & b) { a = max(a, b); }
template <class T> inline void setmin(T & a, T const & b) { a = min(a, b); }
template <typename X, typename T> auto vectors(X x, T a) { return vector<T>(x, a); }
template <typename X, typename Y, typename Z, typename... Zs> auto vectors(X x, Y y, Z z, Zs... zs) { auto cont = vectors(y, z, zs...); return vector<decltype(cont)>(x, cont); }
template <class T> using reversed_priority_queue = priority_queue<T, vector<T>, greater<T> >;

int main() {
    constexpr int inf = 1e9+7;
    while (true) {
        // input
        int n, m, company, start, goal; scanf("%d%d%d%d%d", &n, &m, &company, &start, &goal); -- start; -- goal;
        if (n == 0) break;
        auto g = vectors(company, n, vector<pair<int, int> >());
        repeat (i, m) {
            int x, y, d, c; scanf("%d%d%d%d", &x, &y, &d, &c); -- x; -- y; -- c;
            g[c][x].emplace_back(y, d);
            g[c][y].emplace_back(x, d);
        }
        vector<int> p(company);
        repeat (c, company) {
            scanf("%d", &p[c]);
        }
        vector<vector<int> > q(company);
        vector<vector<int> > r(company);
        repeat (c, company) {
            q[c].resize(p[c] - 1);
            repeat (i, p[c] - 1) {
                scanf("%d", &q[c][i]);
            }
            r[c].resize(p[c]);
            repeat (i, p[c]) {
                scanf("%d", &r[c][i]);
            }
        }
        // solve
        // // initialize costs
        auto dist = vectors(company, n, n, inf);
        repeat (c, company) {
            repeat (i, n) {
                dist[c][i][i] = 0;
                for (auto e : g[c][i]) {
                    int j, d; tie(j, d) = e;
                    setmin(dist[c][i][j], d);
                }
            }
            repeat (k, n) repeat (i, n) repeat (j, n) { // Warshall-Floyd
                setmin(dist[c][i][j], dist[c][i][k] + dist[c][k][j]);
            }
        }
        auto cost = vectors(company, n, n, inf);
        repeat (c, company) {
            int max_dist = 0;
            repeat (i, n) repeat (j, n) if (dist[c][i][j] != inf) {
                setmax(max_dist, dist[c][i][j]);
            }
            vector<int> cost_at(max_dist + 3);
            int i = 0;
            repeat (d, cost_at.size() - 1) {
                if (i < p[c] - 1 and d == q[c][i]) ++ i;
                cost_at[d + 1] = cost_at[d] + r[c][i];
            }
            repeat (i, n) repeat (j, n) if (dist[c][i][j] != inf) {
                cost[c][i][j] = cost_at[dist[c][i][j]];
            }
        }
        // // Dijkstra
        vector<int> result(n, inf);
        vector<bool> fixed(n);
        reversed_priority_queue<pair<int, int> > que;
        result[start] = 0;
        que.emplace(0, start);
        while (not que.empty()) {
            int i = que.top().second; que.pop();
            if (fixed[i]) continue;
            fixed[i] = true;
            repeat (j, n) {
                int d = inf;
                repeat (c, company) {
                    setmin(d, result[i] + cost[c][i][j]);
                }
                if (d < result[j]) {
                    result[j] = d;
                    que.emplace(d, j);
                }
            }
        }
        // output
        printf("%d\n", result[goal] == inf ? -1 : result[goal]);
    }
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 4792
final_rank: 3

code_snippet: //#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,n) for (ll i=0;i<(ll)n;i++)
#define rrep(i,n) for (ll i=n-1;i>=(ll)0;i--)
#define loop(i,m,n) for(ll i=m;i<=(ll)n;i++)
#define rloop(i,m,n) for(ll i=m;i>=(ll)n;i--)
#define vl vector<ll>
#define vvl vector<vector<ll>>
#define vdbg(a) rep(ii,a.size()){cout<<a[ii]<<" ";}cout<<endl;
#define vpdbg(a) rep(ii,a.size()){cout<<"{"<<a[ii].first<<","<<a[ii].second<<"} ";}cout<<endl;
#define vvdbg(a) rep(ii,a.size()){rep(jj,a[ii].size()){cout<<a[ii][jj]<<" ";}cout<<endl;}
#define setdbg(a) for(const auto & ii:a){cout<<ii<<" ";}cout<<endl;
#define inf 1e9
#define mod 998244353LL
//#define mod 1000000007LL
#define eps 0.000000001
random_device rnd;// 非決定的な乱数生成器
mt19937 mt(rnd());// メルセンヌ・ツイスタの32ビット版、引数は初期シード

//#include<boost/multiprecision/cpp_int.hpp>
//#define bbi boost::multiprecision::cpp_int
//#include<atcoder/lazysegtree>


//整数同士の累乗の計算をする。
ll power(ll A, ll B) {
	ll result = 1;
	for (ll i=0;i<B;i++){
		result *= A;
	}
	return result;
}

// nのk乗をmodで割った余りを計算
ll power_mod(ll n, ll k){
	long long result = 1;
	while (k > 0){
		if ((k&1) ==1)result=(result*n)%mod;
		n=n*n%mod;
		k >>= 1;
	}
	return result;
}


//受け取った2次元文字の外側に、文字pをコーティングする。
vector<string> pad(vector<string> &s,char p){
	ll h=s.size();
	ll w=s[0].size();
	vector<string> res(h+2,string(w+2,p));
	rep(i,h)rep(j,w)res[i+1][j+1]=s[i][j];
	return res;
}

// Union-Find
struct UnionFind {
	vector<int> par, siz;
	UnionFind(int n) : par(n, -1) , siz(n, 1) { }
	// 根を求める
	int root(int x) {
		if (par[x] == -1) return x;
		else return par[x] = root(par[x]);
	}
	// x と y が同じグループに属するかどうか (根が一致するかどうか)
	bool issame(int x, int y) {
		return root(x) == root(y);
	}
	// x を含むグループと y を含むグループとを併合する
	bool unite(int x, int y) {
		x = root(x), y = root(y);
		if (x == y) return false; 
		if (siz[x] < siz[y]) swap(x, y);
		par[y] = x;
		siz[x] += siz[y];
		return true;
	}
	// x を含むグループのサイズ
	int size(int x) {
		return siz[root(x)];
	}
};


//グリッド問題等用
vl dx={1,0,-1,0};
vl dy={0,1,0,-1};

void warshall_floyd(vvl & d){
	ll n=d.size();
	rep(k,n)rep(i,n)rep(j,n)d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}

ll solve(){
	ll n,m,c,start,goal;
	cin>>n>>m>>c>>start>>goal;
	start--,goal--;
	if(n==0){return 1;}

	vector<vvl> g(c,vvl(n,vl(n,inf)));
	rep(i,m){
		ll x,y,d,cc;
		cin>>x>>y>>d>>cc;
		x--,y--,cc--;
		g[cc][x][y]=min(g[cc][x][y],d);
		g[cc][y][x]=min(g[cc][y][x],d);
	}

	rep(i,c){
		warshall_floyd(g[i]);
	}

	vl p(c);
	rep(i,c)cin>>p[i];

	//cout<<"test"<<endl;

	rep(i,c){
		vl q(p[i]-1);
		vl r(p[i]);
		rep(j,p[i]-1)cin>>q[j];
		rep(j,p[i])cin>>r[j];
		q.push_back(inf);

		vl nedan(20001);
		nedan[0]=0;
		ll ind=0;
		loop(j,1,20000){
			nedan[j]=nedan[j-1]+r[ind];
			if(q[ind]==j)ind++;
		}
		rep(j,n)rep(k,n){
			if(g[i][j][k]==inf)continue;
			g[i][j][k]=nedan[g[i][j][k]];
		}
	}
	vvl wf(n,vl(n,inf));
	rep(i,c)rep(j,n)rep(k,n){
		wf[j][k]=min(wf[j][k],g[i][j][k]);
	}

	warshall_floyd(wf);
	if(wf[start][goal]!=inf)cout<<wf[start][goal]<<"\n";
	else cout<<-1<<"\n";
	return 0;
}

//メイン
int main(){
	while(solve()==0);
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 5032
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rrep(i,start,end) for (ll i = start;i >= (ll)(end);i--)
#define repn(i,end) for(ll i = 0; i <= (ll)(end); i++)
#define reps(i,start,end) for(ll i = start; i < (ll)(end); i++)
#define repsn(i,start,end) for(ll i = start; i <= (ll)(end); i++)
#define each(p,a) for(auto &p:a)
typedef vector<ll> vll;
typedef vector<pair<ll ,ll>> vpll;
typedef vector<vector<ll>> vvll;
typedef set<ll> sll;
typedef map<ll , ll> mpll;
typedef pair<ll ,ll> pll;
typedef tuple<ll , ll , ll> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (ll)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 60;
const ld EPS = 1e-9;
 
ll lceil(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b)+1;}else{return -((-a)/b);}}
ll lfloor(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b);}else{return -((-a)/b)-1;}}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
//0indexed
inline ll topbit(ll a){assert(a != 0);return 63 - __builtin_clzll(a);}
inline ll smlbit(ll a){assert(a != 0);return __builtin_ctzll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

void solve(ll n,ll m,ll C,ll S,ll G){
  S--;
  G--;
  vector<vector<vector<pll>>> g(n,vector<vector<pll>>(C));
  rep(i,m){
    LL(x,y,d,c);
    x--;y--;
    c--;
    g[x][c].push_back({y,d});
    g[y][c].push_back({x,d});
  
  }
  vll P(C);
  cin >> P;
  vector<vector<ll>>Q(C),R(C);
  rep(i,C){
    rep(j,P[i]-1){
      LL(q);
      Q[i].push_back(q);
    }
    rep(j,P[i]){
      LL(r);
      R[i].push_back(r);
    }
  }

  ll maxdist = 20000 + 1;

  vvll Ccost(C,vll(maxdist));

  rep(i,C){
    ll r = R[i][0];
    ll j = 0;
    reps(d,1,maxdist){
      //dでのコストを計算
      Ccost[i][d] = Ccost[i][d-1]+r;
      if(j < P[i]-1 && Q[i][j] == d){
        //rの更新
        r = R[i][j+1];
        j++;
      }
    }
  }

  priority_queue<pll,vpll,greater<pll>> pq;
  vector<ll> dist(n,INF);
  dist[S] = 0;
  pq.push({0,S});

  while(!pq.empty()){
    auto [nowcost,now] = pq.top();
    pq.pop();
    if(dist[now] < nowcost)continue;
    //更新
    rep(i,C)if(!g[now][i].empty()){
      priority_queue<pll,vpll,greater<pll>> npq;
      vector<ll> ndist(n,INF);
      ndist[now] = 0;
      npq.push({0,now});
      while(!npq.empty()){
        auto [ncost,nnow] = npq.top();
        npq.pop();
        if(ndist[nnow] < ncost)continue;
        for(auto &[ny,nd]:g[nnow][i]){
          if(chmin(ndist[ny],ndist[nnow]+nd)){
            npq.push({ndist[ny],ny});
          }
        }
      }
      rep(j,n)if(ndist[j] != INF){
        if(chmin(dist[j],dist[now]+Ccost[i][ndist[j]])){
          pq.push({dist[j],j});
        }
      }
    }
  }
  if(dist[G] ==INF){
    cout << -1 << endl;
  }else{
    cout << dist[G] << endl;
  }

}



int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  while(true){
    LL(n,m,C,S,G);
    if(n == 0 && m == 0 && C == 0 && S == 0 && G == 0)break;
    solve(n,m,C,S,G);
  }


}
accuracy: 1
time_ms: 80
memory_kb: 7148
final_rank: 12

code_snippet: #include <bits/extc++.h>
 
using namespace std;
 
#define rep(i,n) for(int i=0;i<(n);++i)
#define reps(i,n) for(int i=1;i<=(n);++i)
#define all(x) begin(x),end(x)
#define Fixed fixed << setprecision(12)
#define updiv(a, b) (((a) + (b) - 1) / (b))
using pii = pair<int,int>;
constexpr int32_t INF  = 0x3f3f3f3f;
constexpr int_fast64_t LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int mod = 1e9+7;
// constexpr int mod = 998244353;
 
template <class Func>
class FixPoint : Func {
public:
    explicit constexpr FixPoint(Func&& f) noexcept : Func(forward<Func>(f)) {}
 
    template <class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
        return Func::operator()(*this, std::forward<Args>(args)...);
    }
};
 
template <class Func>
static inline constexpr decltype(auto) makeFixPoint(Func&& f) noexcept {
    return FixPoint<Func>{forward<Func>(f)};
}
 
template<class T, class U> istream& operator>>(istream& is, pair<T, U>& p){ is >> p.first >> p.second; return (is); }
template<class T, class U> ostream& operator<<(ostream& os, pair<T, U>& p){ os << p.first << ' ' << p.second; return (os); }
template<class T> istream& operator>>(istream& is, vector<T>& v){ for (auto &&e : v) is >> e; return (is); }
template<class T> ostream& operator<<(ostream& os, vector<T>& v){ for (auto &&e : v) os << e << ' '; return (os); }
 
template <class A, class B> inline bool chmax(A &a, const B &b) { return b > a && (a = b, true); }
template <class A, class B> inline bool chmin(A &a, const B &b) { return b < a && (a = b, true); }
 
template<typename A, typename B, typename F>
inline bool compare(const A &a, const B &b, const F &f) {
    return lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), f);
}
template<typename A, typename B>
inline bool compare(const A &a, const B &b) {
    return lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
}
 
template <class T> using max_heap = priority_queue<T>;
template <class T> using min_heap = priority_queue<T, vector<T>, greater<T> >;
template <class A, class B> using umap = unordered_map<A, B>;
template <class T> using uset = unordered_set<T>;
 
template <class T> using Set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
 
template <class T> void bye(T x){ cout << x << '\n'; exit(0); }
inline int square(int a){ return (a * a); }
 
constexpr int dx[] = {1,0,-1,0,1,1,-1,-1};
constexpr int dy[] = {0,-1,0,1,1,-1,-1,1};

#define ll int64_t

int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout.setf(ios_base::fixed);
    cout.precision(12);

    int n, m, c, s, g;
    while (cin >> n >> m >> c >> s >> g, n) {
        --s, --g;
        vector<vector<tuple<int, int, int> > > graph(n);
        vector dist(c, vector(n, vector(n, (ll) INF)));
        vector cost(c, vector(10000 + 1, 0LL));

        for (int i = 0; i < m; ++i) {
            int x, y, d, ci;
            cin >> x >> y >> d >> ci;
            --x, --y, --ci;
            graph[x].emplace_back(y, d, ci);
            graph[y].emplace_back(x, d, ci);
            chmin(dist[ci][x][y], d);
            chmin(dist[ci][y][x], d);
        }

        vector<int> p(c);
        cin >> p;

        vector<vector<int> > q(c);
        vector<vector<int> > r(c);

        for (int i = 0; i < c; ++i) {
            q[i].resize(p[i] - 1);
            r[i].resize(p[i]);
            for (int j = 0; j < p[i] - 1; ++j) {
                cin >> q[i][j];
            }
            for (int j = 0; j < p[i]; ++j) {
                cin >> r[i][j];
            }

            int k = 0;
            for (int j = 1; j <= 10000; ++j) {
                cost[i][j] = cost[i][j - 1] + r[i][k];
                if (k < p[i] - 1 && q[i][k] == j) k++;
            }
        }

        for (int ci = 0; ci < c; ++ci) {
            for (int i = 0; i < n; ++i) {
                dist[ci][i][i] = 0;
            }

            for (int k = 0; k < n; ++k) {
                for (int i = 0; i < n; ++i) {
                    for (int j = 0; j < n; ++j) {
                        chmin(dist[ci][i][j], dist[ci][i][k] + dist[ci][k][j]);
                    }
                }
            }
        }

        vector res(n, LINF);
        min_heap<pair<ll, int> > pq;

        res[s] = 0;
        pq.emplace(0, s);

        while (!pq.empty()) {
            auto [cur_cost, cur_node] = pq.top();
            pq.pop();
            if (res[cur_node] < cur_cost) continue;
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < c; ++j) {
                    ll cc;
                    ll di = dist[j][cur_node][i];
                    if (di == INF) continue;
                    if (di <= 10000) cc = cost[j][di];
                    else cc = cost[j][10000] + (di - 10000) * r[j].back();
                    if (chmin(res[i], res[cur_node] + cc)) {
                        pq.emplace(res[i], i);
                    }
                }
            }
        }

        // cerr << res << endl;

        cout << (res[g] == LINF ? -1 : res[g]) << '\n';
    }

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

code_snippet: #include <bits/extc++.h>
 
using namespace std;
 
#define rep(i,n) for(int i=0;i<(n);++i)
#define reps(i,n) for(int i=1;i<=(n);++i)
#define all(x) begin(x),end(x)
#define Fixed fixed << setprecision(12)
#define updiv(a, b) (((a) + (b) - 1) / (b))
using pii = pair<int,int>;
constexpr int32_t INF  = 0x3f3f3f3f;
constexpr int_fast64_t LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int mod = 1e9+7;
// constexpr int mod = 998244353;
 
template <class Func>
class FixPoint : Func {
public:
    explicit constexpr FixPoint(Func&& f) noexcept : Func(forward<Func>(f)) {}
 
    template <class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
        return Func::operator()(*this, std::forward<Args>(args)...);
    }
};
 
template <class Func>
static inline constexpr decltype(auto) makeFixPoint(Func&& f) noexcept {
    return FixPoint<Func>{forward<Func>(f)};
}
 
template<class T, class U> istream& operator>>(istream& is, pair<T, U>& p){ is >> p.first >> p.second; return (is); }
template<class T, class U> ostream& operator<<(ostream& os, pair<T, U>& p){ os << p.first << ' ' << p.second; return (os); }
template<class T> istream& operator>>(istream& is, vector<T>& v){ for (auto &&e : v) is >> e; return (is); }
template<class T> ostream& operator<<(ostream& os, vector<T>& v){ for (auto &&e : v) os << e << ' '; return (os); }
 
template <class A, class B> inline bool chmax(A &a, const B &b) { return b > a && (a = b, true); }
template <class A, class B> inline bool chmin(A &a, const B &b) { return b < a && (a = b, true); }
 
template<typename A, typename B, typename F>
inline bool compare(const A &a, const B &b, const F &f) {
    return lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), f);
}
template<typename A, typename B>
inline bool compare(const A &a, const B &b) {
    return lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
}
 
template <class T> using max_heap = priority_queue<T>;
template <class T> using min_heap = priority_queue<T, vector<T>, greater<T> >;
template <class A, class B> using umap = unordered_map<A, B>;
template <class T> using uset = unordered_set<T>;
 
template <class T> using Set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
 
template <class T> void bye(T x){ cout << x << '\n'; exit(0); }
inline int square(int a){ return (a * a); }
 
constexpr int dx[] = {1,0,-1,0,1,1,-1,-1};
constexpr int dy[] = {0,-1,0,1,1,-1,-1,1};

#define int ll
#define ll int64_t

signed main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout.setf(ios_base::fixed);
    cout.precision(12);

    int n, m, c, s, g;
    while (cin >> n >> m >> c >> s >> g, n) {
        --s, --g;
        vector<vector<tuple<int, int, int> > > graph(n);
        vector dist(c, vector(n, vector(n, (ll) INF)));
        vector cost(c, vector(10000 + 1, 0LL));

        for (int i = 0; i < m; ++i) {
            int x, y, d, ci;
            cin >> x >> y >> d >> ci;
            --x, --y, --ci;
            graph[x].emplace_back(y, d, ci);
            graph[y].emplace_back(x, d, ci);
            chmin(dist[ci][x][y], d);
            chmin(dist[ci][y][x], d);
        }

        vector<int> p(c);
        cin >> p;

        vector<vector<int> > q(n);
        vector<vector<int> > r(n);

        for (int i = 0; i < c; ++i) {
            q[i].resize(p[i] - 1);
            r[i].resize(p[i]);
            for (int j = 0; j < p[i] - 1; ++j) {
                cin >> q[i][j];
            }
            for (int j = 0; j < p[i]; ++j) {
                cin >> r[i][j];
            }

            int k = 0;
            for (int j = 1; j <= 10000; ++j) {
                cost[i][j] = cost[i][j - 1] + r[i][k];
                if (k < p[i] - 1 && q[i][k] == j) k++;
            }
        }

        for (int ci = 0; ci < c; ++ci) {
            for (int i = 0; i < n; ++i) {
                dist[ci][i][i] = 0;
            }

            for (int k = 0; k < n; ++k) {
                for (int i = 0; i < n; ++i) {
                    for (int j = 0; j < n; ++j) {
                        chmin(dist[ci][i][j], dist[ci][i][k] + dist[ci][k][j]);
                    }
                }
            }
        }

        vector res(n, LINF);
        min_heap<pair<ll, int> > pq;

        res[s] = 0;
        pq.emplace(0, s);

        while (!pq.empty()) {
            auto [cur_cost, cur_node] = pq.top();
            pq.pop();
            if (res[cur_node] < cur_cost) continue;
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < c; ++j) {
                    ll cc;
                    ll di = dist[j][cur_node][i];
                    if (di == INF) continue;
                    if (di <= 10000) cc = cost[j][di];
                    else cc = cost[j][10000] + (di - 10000) * r[j].back();
                    if (chmin(res[i], res[cur_node] + cc)) {
                        pq.emplace(res[i], i);
                    }
                }
            }
        }

        // cerr << res << endl;

        cout << (res[g] == LINF ? -1 : res[g]) << '\n';
    }

    return 0;
}
accuracy: 0.5
time_ms: 70
memory_kb: 6820
final_rank: 18

code_snippet: #include <bits/extc++.h>
 
using namespace std;
 
#define rep(i,n) for(int i=0;i<(n);++i)
#define reps(i,n) for(int i=1;i<=(n);++i)
#define all(x) begin(x),end(x)
#define Fixed fixed << setprecision(12)
#define updiv(a, b) (((a) + (b) - 1) / (b))
using pii = pair<int,int>;
constexpr int32_t INF  = 0x3f3f3f3f;
constexpr int_fast64_t LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int mod = 1e9+7;
// constexpr int mod = 998244353;
 
template <class Func>
class FixPoint : Func {
public:
    explicit constexpr FixPoint(Func&& f) noexcept : Func(forward<Func>(f)) {}
 
    template <class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
        return Func::operator()(*this, std::forward<Args>(args)...);
    }
};
 
template <class Func>
static inline constexpr decltype(auto) makeFixPoint(Func&& f) noexcept {
    return FixPoint<Func>{forward<Func>(f)};
}
 
template<class T, class U> istream& operator>>(istream& is, pair<T, U>& p){ is >> p.first >> p.second; return (is); }
template<class T, class U> ostream& operator<<(ostream& os, pair<T, U>& p){ os << p.first << ' ' << p.second; return (os); }
template<class T> istream& operator>>(istream& is, vector<T>& v){ for (auto &&e : v) is >> e; return (is); }
template<class T> ostream& operator<<(ostream& os, vector<T>& v){ for (auto &&e : v) os << e << ' '; return (os); }
 
template <class A, class B> inline bool chmax(A &a, const B &b) { return b > a && (a = b, true); }
template <class A, class B> inline bool chmin(A &a, const B &b) { return b < a && (a = b, true); }
 
template<typename A, typename B, typename F>
inline bool compare(const A &a, const B &b, const F &f) {
    return lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), f);
}
template<typename A, typename B>
inline bool compare(const A &a, const B &b) {
    return lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
}
 
template <class T> using max_heap = priority_queue<T>;
template <class T> using min_heap = priority_queue<T, vector<T>, greater<T> >;
template <class A, class B> using umap = unordered_map<A, B>;
template <class T> using uset = unordered_set<T>;
 
template <class T> using Set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
 
template <class T> void bye(T x){ cout << x << '\n'; exit(0); }
inline int square(int a){ return (a * a); }
 
constexpr int dx[] = {1,0,-1,0,1,1,-1,-1};
constexpr int dy[] = {0,-1,0,1,1,-1,-1,1};

#define ll int64_t

int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout.setf(ios_base::fixed);
    cout.precision(12);

    int n, m, c, s, g;
    while (cin >> n >> m >> c >> s >> g, n) {
        --s, --g;
        vector<vector<tuple<int, int, int> > > graph(n);
        vector dist(c, vector(n, vector(n, (ll) INF)));
        vector cost(c, vector(10000 + 1, 0LL));

        for (int i = 0; i < m; ++i) {
            int x, y, d, ci;
            cin >> x >> y >> d >> ci;
            --x, --y, --ci;
            graph[x].emplace_back(y, d, ci);
            graph[y].emplace_back(x, d, ci);
            chmin(dist[ci][x][y], d);
            chmin(dist[ci][y][x], d);
        }

        vector<int> p(c);
        cin >> p;

        vector<vector<int> > q(n);
        vector<vector<int> > r(n);

        for (int i = 0; i < c; ++i) {
            q[i].resize(p[i] - 1);
            r[i].resize(p[i]);
            for (int j = 0; j < p[i] - 1; ++j) {
                cin >> q[i][j];
            }
            for (int j = 0; j < p[i]; ++j) {
                cin >> r[i][j];
            }

            int k = 0;
            for (int j = 1; j <= 10000; ++j) {
                cost[i][j] = cost[i][j - 1] + r[i][k];
                if (k < p[i] - 1 && q[i][k] == j) k++;
            }
        }

        for (int ci = 0; ci < c; ++ci) {
            for (int i = 0; i < n; ++i) {
                dist[ci][i][i] = 0;
            }

            for (int k = 0; k < n; ++k) {
                for (int i = 0; i < n; ++i) {
                    for (int j = 0; j < n; ++j) {
                        chmin(dist[ci][i][j], dist[ci][i][k] + dist[ci][k][j]);
                    }
                }
            }
        }

        vector res(n, LINF);
        min_heap<pair<ll, int> > pq;

        res[s] = 0;
        pq.emplace(0, s);

        while (!pq.empty()) {
            auto [cur_cost, cur_node] = pq.top();
            pq.pop();
            if (res[cur_node] < cur_cost) continue;
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < c; ++j) {
                    ll cc;
                    ll di = dist[j][cur_node][i];
                    if (di == INF) continue;
                    if (di <= 10000) cc = cost[j][di];
                    else cc = cost[j][10000] + (di - 10000) * r[j].back();
                    if (cc < 0) return 0;
                    if (chmin(res[i], res[cur_node] + cc)) {
                        pq.emplace(res[i], i);
                    }
                }
            }
        }

        // cerr << res << endl;

        cout << (res[g] == LINF ? -1 : res[g]) << '\n';
    }

    return 0;
}
accuracy: 0.5
time_ms: 90
memory_kb: 6772
final_rank: 19

code_snippet: #include <bits/extc++.h>
 
using namespace std;
 
#define rep(i,n) for(int i=0;i<(n);++i)
#define reps(i,n) for(int i=1;i<=(n);++i)
#define all(x) begin(x),end(x)
#define Fixed fixed << setprecision(12)
#define updiv(a, b) (((a) + (b) - 1) / (b))
using pii = pair<int,int>;
constexpr int32_t INF  = 0x3f3f3f3f;
constexpr int_fast64_t LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int mod = 1e9+7;
// constexpr int mod = 998244353;
 
template <class Func>
class FixPoint : Func {
public:
    explicit constexpr FixPoint(Func&& f) noexcept : Func(forward<Func>(f)) {}
 
    template <class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
        return Func::operator()(*this, std::forward<Args>(args)...);
    }
};
 
template <class Func>
static inline constexpr decltype(auto) makeFixPoint(Func&& f) noexcept {
    return FixPoint<Func>{forward<Func>(f)};
}
 
template<class T, class U> istream& operator>>(istream& is, pair<T, U>& p){ is >> p.first >> p.second; return (is); }
template<class T, class U> ostream& operator<<(ostream& os, pair<T, U>& p){ os << p.first << ' ' << p.second; return (os); }
template<class T> istream& operator>>(istream& is, vector<T>& v){ for (auto &&e : v) is >> e; return (is); }
template<class T> ostream& operator<<(ostream& os, vector<T>& v){ for (auto &&e : v) os << e << ' '; return (os); }
 
template <class A, class B> inline bool chmax(A &a, const B &b) { return b > a && (a = b, true); }
template <class A, class B> inline bool chmin(A &a, const B &b) { return b < a && (a = b, true); }
 
template<typename A, typename B, typename F>
inline bool compare(const A &a, const B &b, const F &f) {
    return lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), f);
}
template<typename A, typename B>
inline bool compare(const A &a, const B &b) {
    return lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
}
 
template <class T> using max_heap = priority_queue<T>;
template <class T> using min_heap = priority_queue<T, vector<T>, greater<T> >;
template <class A, class B> using umap = unordered_map<A, B>;
template <class T> using uset = unordered_set<T>;
 
template <class T> using Set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
 
template <class T> void bye(T x){ cout << x << '\n'; exit(0); }
inline int square(int a){ return (a * a); }
 
constexpr int dx[] = {1,0,-1,0,1,1,-1,-1};
constexpr int dy[] = {0,-1,0,1,1,-1,-1,1};

#define ll int64_t

int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout.setf(ios_base::fixed);
    cout.precision(12);

    int n, m, c, s, g;
    while (cin >> n >> m >> c >> s >> g, n) {
        --s, --g;
        vector<vector<tuple<int, int, int> > > graph(n);
        vector dist(c, vector(n, vector(n, (ll) INF)));
        vector cost(c, vector(10000 + 1, 0LL));

        for (int i = 0; i < m; ++i) {
            int x, y, d, ci;
            cin >> x >> y >> d >> ci;
            --x, --y, --ci;
            graph[x].emplace_back(y, d, ci);
            graph[y].emplace_back(x, d, ci);
            chmin(dist[ci][x][y], d);
            chmin(dist[ci][y][x], d);
        }

        vector<int> p(c);
        cin >> p;

        vector<vector<int> > q(n);
        vector<vector<int> > r(n);

        for (int i = 0; i < c; ++i) {
            q[i].resize(p[i] - 1);
            r[i].resize(p[i]);
            for (int j = 0; j < p[i] - 1; ++j) {
                cin >> q[i][j];
            }
            for (int j = 0; j < p[i]; ++j) {
                cin >> r[i][j];
            }

            int k = 0;
            for (int j = 1; j <= 10000; ++j) {
                cost[i][j] = cost[i][j - 1] + r[i][k];
                if (k < p[i] - 1 && q[i][k] == j) k++;
            }
        }

        for (int ci = 0; ci < c; ++ci) {
            for (int i = 0; i < n; ++i) {
                dist[ci][i][i] = 0;
            }

            for (int k = 0; k < n; ++k) {
                for (int i = 0; i < n; ++i) {
                    for (int j = 0; j < n; ++j) {
                        chmin(dist[ci][i][j], dist[ci][i][k] + dist[ci][k][j]);
                    }
                }
            }
        }

        vector res(n, LINF);
        min_heap<pair<ll, int> > pq;

        res[s] = 0;
        pq.emplace(0, s);

        while (!pq.empty()) {
            auto [cur_cost, cur_node] = pq.top();
            pq.pop();
            if (res[cur_node] < cur_cost) continue;
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < c; ++j) {
                    ll cc;
                    ll di = dist[j][cur_node][i];
                    if (di == INF) continue;
                    if (di <= 10000) cc = cost[j][di];
                    else cc = cost[j][10000] + (di - 10000) * r[j].back();
                    if (chmin(res[i], res[cur_node] + cc)) {
                        pq.emplace(res[i], i);
                    }
                }
            }
        }

        // cerr << res << endl;

        cout << (res[g] == LINF ? -1 : res[g]) << '\n';
    }

    return 0;
}
accuracy: 0.5
time_ms: 100
memory_kb: 6620
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<int,int>;
using vi = vector<int>;
using vll = vector<ll>;
using vvi = vector<vi>;
using vvll = vector<vll>;
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define FOR(i, a, b) for(ll i = a; i < (ll)(b); i++)
#define all(a) (a).begin(),(a).end()
constexpr int INF = 1001001001;
constexpr ll LINF = 1001001001001001001ll;
constexpr int DX[] = {1, 0, -1, 0};
constexpr int DY[] = {0, 1, 0, -1};

struct Edge{
    int to, d, c;
    Edge(int to, int d, int c): to(to), d(d), c(c){}
};
bool solve(){
    int n, m, c, s, t;
    cin >> n >> m >> c >> s >> t;
    s--;t--;
    if(n == 0) return false;
    vector<vector<Edge>> g(n);
    rep(i, m){
        int x, y, d, cpy;
        cin >> x >> y >> d >> cpy;
        x--;y--;
        cpy--;
        g[x].emplace_back(y, d, cpy);
        g[y].emplace_back(x, d, cpy);
    }
    vector<int> p(c);
    rep(i, c){
        cin >> p[i];
    }
    vector<vector<pair<int, int>>> qr(c);
    rep(i, c){
        qr[i].resize(p[i]+1, {INF, INF});
        qr[i][0].first = 0;
        rep(j, p[i]-1){
            cin >> qr[i][j+1].first;
        }
        rep(j, p[i]){
            cin >> qr[i][j].second;
        }
    }
    rep(i, c){
        cout << "company' " << i << endl;
        rep(j, p[i]){
            cout << qr[i][j].first << " " << qr[i][j].second << endl;
        }
        cout << endl;
    }
    // cost, v, d, id_d, c
    using pqInfo = pair<pair<int, int>, pair<pair<int, int>, int>>;
    priority_queue<pqInfo, vector<pqInfo>, greater<pqInfo>> que;
    const int MAX_DIST = 10005;
    vector<vector<vector<int>>> cost(n, vector<vector<int>>(c, vector<int>(MAX_DIST, INF)));
    cost[s][0][0] = 0;
    que.push({{0, s}, {{0, 0}, 0}});
    while(!que.empty()){
        auto [costv, dc] = que.top();
        cout << costv.second << " " << dc.first.first << " " << dc.second << " " << costv.first << endl;
        que.pop();
        if(costv.second == t){
            cout << costv.first << endl;
            return true;
        }
        int v = costv.second;
        for(Edge e : g[costv.second]){
            if(e.c == dc.second){
                int ncost = costv.first;
                int nd = dc.first.first + e.d;
                int di = dc.first.second;
                int d = dc.first.first;
                while(qr[dc.second][di+1].first <= nd){
                    ncost += qr[dc.second][di].second*(qr[dc.second][di+1].first - d);
                    d = qr[dc.second][di+1].first;
                    di++;
                }
                ncost += qr[dc.second][di].second*(nd - d);
                if(cost[v][dc.second][min(nd, MAX_DIST-1)] > ncost){
                    cost[v][dc.second][min(nd, MAX_DIST-1)] = ncost;
                    que.push({{ncost, e.to}, {{min(nd, MAX_DIST-1), di}, dc.second}});
                }
            }
            else{
                int ncost = costv.first;
                int nd = e.d;
                int di = 0;
                int d = 0;
                while(qr[e.c][di+1].first <= nd){
                    ncost += qr[e.c][di].second*(qr[e.c][di+1].first - d);
                    d = qr[e.c][di+1].first;
                    di++;
                }
                ncost += qr[e.c][di].second*(nd - d);
                if(cost[v][e.c][min(nd, MAX_DIST-1)] > ncost){
                    cost[v][e.c][min(nd, MAX_DIST-1)] = ncost;
                    que.push({{ncost, e.to}, {{min(nd, MAX_DIST-1), di}, e.c}});
                }
            }
        }
    }
    cout << -1 << endl;
    return true;
}

vector<vector<int>> warshall_floyd(int n, vector<vector<Edge>> es){
    vector<vector<int>> dist(n, vector<int>(n, INF));
    rep(i, n){
        for(Edge e : es[i]){
            dist[i][e.to] = min(dist[i][e.to], e.d);
        }
    }
    rep(k, n){
        rep(i, n){
            rep(j, n){
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    return dist;
}
bool solve2(){
    int n, m, c, s, t;
    cin >> n >> m >> c >> s >> t;
    s--;t--;
    if(n == 0) return false;
    vector<vector<vector<Edge>>> g(c, vector<vector<Edge>>(n));
    rep(i, m){
        int x, y, d, cpy;
        cin >> x >> y >> d >> cpy;
        x--;y--;
        cpy--;
        g[cpy][x].emplace_back(y, d, cpy);
        g[cpy][y].emplace_back(x, d, cpy);
    }
    vector<int> p(c);
    rep(i, c){
        cin >> p[i];
    }
    vector<vector<pair<int, int>>> qr(c);
    rep(i, c){
        qr[i].resize(p[i]+1, {INF, INF});
        qr[i][0].first = 0;
        rep(j, p[i]-1){
            cin >> qr[i][j+1].first;
        }
        rep(j, p[i]){
            cin >> qr[i][j].second;
        }
    }
    vector<vvi> dists(c);
    rep(i, c){
        dists[i] = warshall_floyd(n, g[i]);
    }
    vvi cost(n, vi(n, INF));
    auto get_cost = [&](int cpy, int distance) -> int{
        int di = 0;
        int nowd = 0;
        int ret = 0;
        while(qr[cpy][di+1].first <= distance){
            ret += qr[cpy][di].second*(qr[cpy][di+1].first - nowd);
            nowd = qr[cpy][di+1].first;
            di++;
        }
        ret += qr[cpy][di].second*(distance - nowd);
        return ret;
    };
    rep(k, c){
        rep(i, n){
            rep(j, n){
                if(dists[k][i][j] == INF) continue;
                cost[i][j] = min(cost[i][j], get_cost(k, dists[k][i][j]));
            }
        }
    }
    rep(k, n){
        rep(i, n){
            rep(j, n){
                cost[i][j] = min(cost[i][j], cost[i][k] + cost[k][j]);
            }
        }
    }
    cout << (cost[s][t] == INF ? -1 : cost[s][t]) << endl;
    return true;
}
int main(){
    bool con = true;
    while(con){
        con = solve2();
    }
}
accuracy: 1
time_ms: 80
memory_kb: 4604
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    while(true){
        int n, m, c, s, g;
        cin >> n >> m >> c >> s >> g;
        if(n==0 && m==0 && c==0 && s==0 && g==0) break;
        s--; g--;

        // 1) 各社ごとに距離行列を初期化
        vector<vector<vector<int>>> dist(c,
            vector<vector<int>>(n, vector<int>(n, INF)));
        for(int j=0;j<c;j++){
            for(int i=0;i<n;i++) dist[j][i][i] = 0;
        }

        // 1-2) 路線情報読み込み → 各社ごとの距離行列に格納
        for(int i=0;i<m;i++){
            int x,y,d,ci;
            cin >> x >> y >> d >> ci;
            x--; y--; ci--;
            dist[ci][x][y] = min(dist[ci][x][y], d);
            dist[ci][y][x] = min(dist[ci][y][x], d);
        }

        // 2) 各社ごとに Floyd-Warshall で全点対間最短距離を計算
        for(int j=0;j<c;j++){
            for(int k=0;k<n;k++){
                for(int i=0;i<n;i++){
                    if(dist[j][i][k]==INF) continue;
                    for(int l=0;l<n;l++){
                        if(dist[j][k][l]==INF) continue;
                        dist[j][i][l] = min(dist[j][i][l],
                                            dist[j][i][k] + dist[j][k][l]);
                    }
                }
            }
        }

        // 3) 各社の運賃テーブルを読み込み（距離ごとの料金）
        vector<int> p(c); // 運賃段階の数
        for(int j=0;j<c;j++) cin >> p[j];
        vector<vector<int>> q(c), r(c); // q: 各段階の距離, r: 各段階の単価
        for(int j=0;j<c;j++){
            q[j].resize(max(0, p[j]-1));
            for(int k=0;k<p[j]-1;k++) cin >> q[j][k];
            r[j].resize(p[j]);
            for(int k=0;k<p[j];  k++) cin >> r[j][k];
        }

        // 4) 運賃計算関数（会社 j, 距離 z → 運賃）
        auto calcFare = [&](int j, int z){
            int fare = 0, prevQ = 0;
            for(int k=0;k<p[j] && z>0; k++){
                int limit = (k < p[j]-1 ? q[j][k] - prevQ : z);
                int use = min(limit, z);
                fare += use * r[j][k];
                z -= use;
                prevQ += use;
            }
            return fare;
        };

        // 5) 完全グラフ上に隣接リストを作成（各社の路線に対して運賃付きで辺を作成）
        vector<vector<pair<int,int>>> adj(n);
        for(int j=0;j<c;j++){
            for(int u=0;u<n;u++){
                for(int v=0;v<n;v++){
                    if(u!=v && dist[j][u][v]<INF){
                        int f = calcFare(j, dist[j][u][v]);
                        adj[u].emplace_back(v, f);
                    }
                }
            }
        }

        // 6) Dijkstra 法で最小運賃を求める
        vector<int> cost(n, INF);
        priority_queue<pair<int,int>,
            vector<pair<int,int>>, greater<>> pq;
        cost[s] = 0;
        pq.emplace(0, s);

        while(!pq.empty()){
            auto [cst, u] = pq.top(); pq.pop();
            if(cst > cost[u]) continue;
            if(u == g) break;
            for(auto [v, w] : adj[u]){
                if(cost[v] > cst + w){
                    cost[v] = cst + w;
                    pq.emplace(cost[v], v);
                }
            }
        }

        // 7) 最終的な答えを出力
        cout << (cost[g]==INF ? -1 : cost[g]) << "\n";
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 5732
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    while(true){
        int n, m, c, s, g;
        cin >> n >> m >> c >> s >> g;
        if(n==0 && m==0 && c==0 && s==0 && g==0) break;
        s--; g--;

        // 1) 各社ごとに距離行列を初期化
        vector<vector<vector<int>>> dist(c,
            vector<vector<int>>(n, vector<int>(n, INF)));
        for(int j=0;j<c;j++){
            for(int i=0;i<n;i++) dist[j][i][i] = 0;
        }
        // 路線情報読み込み
        for(int i=0;i<m;i++){
            int x,y,d,ci;
            cin >> x >> y >> d >> ci;
            x--; y--; ci--;
            dist[ci][x][y] = min(dist[ci][x][y], d);
            dist[ci][y][x] = min(dist[ci][y][x], d);
        }

        // 2) Floyd–Warshall で各社の全点対間最短距離
        for(int j=0;j<c;j++){
            for(int k=0;k<n;k++){
                for(int i=0;i<n;i++){
                    if(dist[j][i][k]==INF) continue;
                    for(int l=0;l<n;l++){
                        if(dist[j][k][l]==INF) continue;
                        dist[j][i][l] = min(dist[j][i][l],
                                            dist[j][i][k] + dist[j][k][l]);
                    }
                }
            }
        }

        // 3) 各社の運賃テーブル読み込み
        vector<int> p(c);
        for(int j=0;j<c;j++) cin >> p[j];
        vector<vector<int>> q(c), r(c);
        for(int j=0;j<c;j++){
            q[j].resize(max(0, p[j]-1));
            for(int k=0;k<p[j]-1;k++) cin >> q[j][k];
            r[j].resize(p[j]);
            for(int k=0;k<p[j];  k++) cin >> r[j][k];
        }

        // 4) 運賃計算関数（会社 j, 距離 z → fare）
        auto calcFare = [&](int j, int z){
            int fare = 0, prevQ = 0;
            for(int k=0;k<p[j] && z>0; k++){
                int limit = (k < p[j]-1 ? q[j][k] - prevQ : z);
                int use = min(limit, z);
                fare += use * r[j][k];
                z -= use;
                prevQ += use;
            }
            return fare;
        };

        // 5) 完全グラフ上の隣接リスト作成
        vector<vector<pair<int,int>>> adj(n);
        for(int j=0;j<c;j++){
            for(int u=0;u<n;u++){
                for(int v=0;v<n;v++){
                    if(u!=v && dist[j][u][v]<INF){
                        int f = calcFare(j, dist[j][u][v]);
                        adj[u].emplace_back(v, f);
                    }
                }
            }
        }

        // 6) Dijkstra で最小運賃
        vector<int> cost(n, INF);
        priority_queue<pair<int,int>,
            vector<pair<int,int>>, greater<>> pq;
        cost[s] = 0;
        pq.emplace(0, s);

        while(!pq.empty()){
            auto [cst, u] = pq.top(); pq.pop();
            if(cst > cost[u]) continue;
            if(u == g) break;
            for(auto [v, w] : adj[u]){
                if(cost[v] > cst + w){
                    cost[v] = cst + w;
                    pq.emplace(cost[v], v);
                }
            }
        }

        cout << (cost[g]==INF ? -1 : cost[g]) << "\n";
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 5884
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = (1LL<<60);

struct FareTable {
    vector<int> q;        // 分割点 q_1 … q_{p-1}
    vector<int> r;        // 単価   r_1 … r_p
    ll operator()(int dist) const {
        if (dist==0) return 0;
        ll cost = 0;
        int prev = 0;
        int seg  = 0;
        while (dist > 0) {
            int lim = (seg < (int)q.size() ? q[seg] : INT_MAX);
            int len = min(dist, lim - prev);
            cost += 1LL * len * r[seg];
            dist -= len;
            prev += len;
            if (prev == lim) ++seg;        // 次の区間へ
        }
        return cost;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while (true) {
        int n,m,c,s,g;                     // 入力ヘッダ
        if(!(cin>>n>>m>>c>>s>>g)) return 0;
        if(n==0) break;
        --s; --g;                          // 0-index
        struct Edge{int u,v,d,comp;};
        vector<Edge> edges(m);
        for(auto& e:edges){
            cin>>e.u>>e.v>>e.d>>e.comp;
            --e.u; --e.v; --e.comp;
        }
        vector<int> p(c);
        for(int& v:p) cin>>v;

        vector<FareTable> fare(c);
        for(int j=0;j<c;++j){
            int pj=p[j];
            fare[j].q.resize(max(0,pj-1));
            for(int k=0;k<pj-1;++k) cin>>fare[j].q[k];
            fare[j].r.resize(pj);
            for(int k=0;k<pj;++k) cin>>fare[j].r[k];
        }

        /* --- 会社ごとの最短距離 --- */
        vector<vector<vector<int>>> dist(c,
            vector<vector<int>>(n, vector<int>(n, 1e9)));

        for(int j=0;j<c;++j)
            for(int i=0;i<n;++i) dist[j][i][i]=0;

        for(auto e:edges){
            dist[e.comp][e.u][e.v]=
            dist[e.comp][e.v][e.u]=
                min(dist[e.comp][e.u][e.v], e.d);
        }
        for(int j=0;j<c;++j){
            for(int k=0;k<n;++k)
              for(int i=0;i<n;++i){
                  if(dist[j][i][k]==1e9) continue;
                  for(int v=0;v<n;++v){
                      dist[j][i][v]=min(dist[j][i][v],
                          dist[j][i][k]+dist[j][k][v]);
                  }
              }
        }

        /* --- メタグラフのコスト行列 --- */
        vector<vector<ll>> meta(n, vector<ll>(n, INF));
        for(int j=0;j<c;++j){
            for(int u=0;u<n;++u)
              for(int v=0;v<n;++v){
                  int d = dist[j][u][v];
                  if(d==1e9) continue;
                  ll cost = fare[j](d);
                  meta[u][v] = min(meta[u][v], cost);
              }
        }

        /* --- Dijkstra --- */
        vector<ll> d(n, INF);
        d[s]=0;
        priority_queue<pair<ll,int>,vector<pair<ll,int>>,
                       greater<pair<ll,int>>> pq;
        pq.emplace(0,s);
        while(!pq.empty()){
            auto [du,u]=pq.top(); pq.pop();
            if(du!=d[u]) continue;
            if(u==g) break;
            for(int v=0;v<n;++v){
                if(meta[u][v]==INF) continue;
                ll nd = du + meta[u][v];
                if(nd<d[v]){
                    d[v]=nd;
                    pq.emplace(nd,v);
                }
            }
        }
        cout<<(d[g]==INF?-1:d[g])<<"\n";
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 4436
final_rank: 2

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;

/*
 * 1. 各会社ごとにワーシャルフロイドで最短距離を計算
 * 2. 運賃表をもとに各会社の距離→運賃を求める関数を作っておく
 * 3. 得られた距離に対して、運賃を計算して、新たな辺を追加
 * 4. 作ったグラフに対してダイクストラで答えを求める
 */

const ll INF = 4e18;
using edge = tuple<int, ll, int>;

void warshall_floyd(vector<vector<ll>>& d, int n)
{
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
            }
        }
    }
}

void solve(int N, int M, int C, int S, int G)
{
    vector<vector<edge>> E(N);
    vector c_dist(C, vector<vector<ll>>(N, vector<ll>(N, INF)));
    for (int i = 0; i < M; i++) {
        int x, y, c;
        ll d;
        cin >> x >> y >> d >> c, x--, y--, c--;

        c_dist[c][x][y] = min(c_dist[c][x][y], d);
        c_dist[c][y][x] = min(c_dist[c][x][y], d);
    }

    vector<int> P(C);
    vector<vector<ll>> Q(C), R(C);
    for (auto& p: P) { cin >> p; }
    for (int c = 0; c < C; c++) {
        Q[c].resize(P[c] - 1);
        R[c].resize(P[c]);
        for (int i = 0; i < P[c] - 1; i++) cin >> Q[c][i];
        for (int i = 0; i < P[c]; i++) cin >> R[c][i];
    }

    vector<vector<ll>> pref(C);
    for (int c = 0; c < C; c++) {
        if (P[c] <= 1) continue;
        pref[c].resize(P[c] - 1);
        pref[c][0] = Q[c][0] * R[c][0];
        for (int i = 1; i < P[c] - 1; i++) {
            ll len = Q[c][i] - Q[c][i - 1];
            pref[c][i] = pref[c][i - 1] + len * R[c][i];
        }
    }

    // 会社ごとにワーシャルフロイド
    for (int c = 0; c < C; c++) { warshall_floyd(c_dist[c], N); }

    auto calc_cost = [&](int c, ll d) {
        if (d == INF) return INF;
        auto it = upper_bound(Q[c].begin(), Q[c].end(), d);
        int seg = it - Q[c].begin();
        ll prev_cost = seg > 0 ? pref[c][seg - 1] : 0;
        ll prev_dist = seg > 0 ? Q[c][seg - 1] : 0;
        return prev_cost + (d - prev_dist) * R[c][seg];
    };

    // グラフに新たな辺を追加
    for (int c = 0; c < C; c++) {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (c_dist[c][i][j] == INF) continue;
                ll cost = calc_cost(c, c_dist[c][i][j]);
                E[i].emplace_back(j, cost, c);
            }
        }
    }

    // // ダイクストラで答えを求める
    vector<ll> dist(N, INF);
    priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;
    dist[S] = 0;
    pq.emplace(0, S);
    while (!pq.empty()) {
        auto [cost, u] = pq.top();
        pq.pop();
        if (dist[u] < cost) continue;
        for (auto& [v, w, c]: E[u]) {
            if (dist[v] > cost + w) {
                dist[v] = cost + w;
                pq.emplace(dist[v], v);
            }
        }
    }

    cout << (dist[G] == INF ? -1 : dist[G]) << endl;
}

int main()
{
    while (true) {
        int N, M, C, S, G;
        cin >> N >> M >> C >> S >> G, S--, G--;
        if (N == 0) break;
        solve(N, M, C, S, G);
    }
}
accuracy: 1
time_ms: 80
memory_kb: 10336
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = (ll)4e18;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    while (true) {
        int N, M, C, s, g;
        cin >> N >> M >> C >> s >> g;
        if (!cin || N == 0) break;
        s--; g--;

        // 1) Read edges and build per-company distance matrix
        vector<vector<vector<ll>>> dist(C, vector<vector<ll>>(N, vector<ll>(N, INF)));
        for (int j = 0; j < C; j++) {
            for (int i = 0; i < N; i++) dist[j][i][i] = 0;
        }
        for (int i = 0; i < M; i++) {
            int x, y, d, c;
            cin >> x >> y >> d >> c;
            x--; y--; c--;
            dist[c][x][y] = min(dist[c][x][y], (ll)d);
            dist[c][y][x] = min(dist[c][y][x], (ll)d);
        }

        // Floyd-Warshall per company
        for (int j = 0; j < C; j++) {
            for (int k = 0; k < N; k++)
                for (int i = 0; i < N; i++) if (dist[j][i][k] < INF)
                    for (int l = 0; l < N; l++) {
                        ll nd = dist[j][i][k] + dist[j][k][l];
                        if (nd < dist[j][i][l]) dist[j][i][l] = nd;
                    }
        }

        // 2) Read fare tables for each company
        vector<int> p(C);
        for (int j = 0; j < C; j++) cin >> p[j];

        vector<vector<int>> q(C), r(C);
        for (int j = 0; j < C; j++) {
            if (p[j] > 1) {
                q[j].resize(p[j] - 1);
                for (int k = 0; k < p[j] - 1; k++) cin >> q[j][k];
            }
            r[j].resize(p[j]);
            for (int k = 0; k < p[j]; k++) cin >> r[j][k];
        }

        // Precompute prefix costs up to each breakpoint
        vector<vector<ll>> prefix(C);
        for (int j = 0; j < C; j++) {
            if (p[j] <= 1) continue;
            prefix[j].resize(p[j] - 1);
            // cost up to q[j][0]
            prefix[j][0] = (ll)q[j][0] * r[j][0];
            for (int k = 1; k < p[j] - 1; k++) {
                ll len = q[j][k] - q[j][k - 1];
                prefix[j][k] = prefix[j][k - 1] + len * r[j][k];
            }
        }

        // fare function: cost for distance z on company j
        auto fare = [&](int j, ll z) {
            if (z <= 0) return 0LL;
            int seg = 0;
            if (!q[j].empty()) {
                // find first q[j][seg] >= z
                auto it = upper_bound(q[j].begin(), q[j].end(), (int)z);
                seg = it - q[j].begin();
            }
            ll prev_cost = 0;
            ll prev_dist = 0;
            if (seg > 0) {
                prev_cost = prefix[j][seg - 1];
                prev_dist = q[j][seg - 1];
            }
            return prev_cost + (z - prev_dist) * r[j][seg];
        };

        // 3) Build meta-graph edges: from u to v with cost via company j
        vector<vector<pair<int,ll>>> metaE(N);
        for (int j = 0; j < C; j++) {
            for (int u = 0; u < N; u++) {
                for (int v = 0; v < N; v++) {
                    if (u == v) continue;
                    ll d = dist[j][u][v];
                    if (d < INF) {
                        ll cst = fare(j, d);
                        metaE[u].emplace_back(v, cst);
                    }
                }
            }
        }

        // 4) Dijkstra on meta-graph from s to g
        vector<ll> dmeta(N, INF);
        dmeta[s] = 0;
        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;
        pq.emplace(0, s);

        while (!pq.empty()) {
            auto [cd, u] = pq.top(); pq.pop();
            if (cd > dmeta[u]) continue;
            if (u == g) break;
            for (auto& [v, w] : metaE[u]) {
                ll nd = cd + w;
                if (nd < dmeta[v]) {
                    dmeta[v] = nd;
                    pq.emplace(nd, v);
                }
            }
        }

        ll ans = dmeta[g];
        if (ans >= INF/2) cout << -1 << "\n";
        else cout << ans << "\n";
    }

    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 8404
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define pi pair<int, int>
#define fi first
#define se second
#define pb push_back
const int N = 100, M = 10000, MAX_EDGE = 200, MAX_COMPANIES = 20, INF = 1e9;
pi edges[M];
vector<pi> vec[N];
int cost_of_flight[MAX_COMPANIES][MAX_EDGE * N];
int real_cost[N][N];
int dist[N][N];
signed main() {
    cin.tie(0); ios_base::sync_with_stdio(0);
    int n, m, c, s, g;
    while (cin >> n >> m >> c >> s >> g) {
//        cerr << n << ' ' << m << " " << c << " " << s << " " << g << endl;
        if (n == 0 && m == 0 && c == 0 && s == 0 && g == 0) break;
        s--; g--;
        for (int i = 0; i < n; ++i) vec[i].clear();
        for (int i = 0; i < m; ++i) {
            int x, y, c, d;
            cin >> x >> y >> d >> c;
            c--;
            x--; y--;
            edges[i] = {c, d};
            vec[x].pb({y, i});
            vec[y].pb({x, i});
        }
        vector<int> section_number(c);
        for (int company = 0; company < c; ++company) cin >> section_number[company];
        for (int company = 0; company < c; ++company) {
            vector<int> q, r;
            for (int j = 0; j < section_number[company] - 1; ++j) {
                int x;
                cin >> x;
                q.pb(x);
            }
            for (int j = 0; j < section_number[company]; ++j) {
                int x;
                cin >> x;
                r.pb(x);
            }
            int current_index = 0;
            for (int distance = 1; distance < MAX_EDGE * N; ++distance) {
                if (current_index < q.size() && distance > q[current_index]) ++current_index;
                cost_of_flight[company][distance] = cost_of_flight[company][distance - 1] + r[current_index];
            }
        }
        for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) real_cost[i][j] = INF;
        for (int company = 0; company < c; ++company) {
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < n; ++j) dist[i][j] = i == j ? 0 : INF;
            }
            for (int v = 0; v < n; ++v) {
                for (auto [u, edge]: vec[v]) {
                    auto [new_company, length] = edges[edge];
                    if (new_company != company) continue;
                    dist[v][u] = min(dist[v][u], length);
                }
            }
            for (int k = 0; k < n; ++k) {
                for (int i = 0; i < n; ++i) {
                    for (int j = 0; j < n; ++j) {
                        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
                    }
                }
            }
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (dist[i][j] == INF) continue;
                    real_cost[i][j] = min(real_cost[i][j], cost_of_flight[company][dist[i][j]]);
                }
            }
        }
        vector<int> result(n, INF), used(n, 0);
        result[s] = 0;
        while (1) {
            pi minimum = {INF, INF};
            for (int i = 0; i < n; ++i) {
                if (used[i]) continue;
                minimum = min(minimum, pi{result[i], i});
            }
            if (minimum.fi == INF) break;
            int v = minimum.se;
            used[v] = 1;
            for (int u = 0; u < n; ++u) {
                result[u] = min(result[u], result[v] + real_cost[v][u]);
            }
        }
        cout << (result[g] == INF ? -1 : result[g]) << "\n";
    }
}
accuracy: 1
time_ms: 90
memory_kb: 5324
final_rank: 8