#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <climits>
#include <cstring>
#include <cassert>


using namespace std;
#define SZ(x) (int)(x.size())
#define REP(i, n) for(int i=0;i<n;++i)
#define FOR(i, a, b) for(int i=a;i<b;++i)
#define RREP(i, n) for(int i=n-1;i>=0;--i)
#define RFOR(i, a, b) for(int i=b-1;i>=a;--i)

#define all(x) begin(x),end(x)
#define dump(x) cerr<<#x<<" = "<<(x)<<endl
#define debug(x) cerr<<#x<<" = "<<(x)<<" (L"<<__LINE__<<")"<< endl;

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using P = pair<int, int>;
const double eps = 1e-8;
const ll MOD = 1000000007;
const int INF = INT_MAX / 2;
const ll LINF = LLONG_MAX / 2;

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 (b < a) {
        a = b;
        return true;
    }
    return false;
}


template<typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> p) {
    os << p.first << ":" << p.second;
    return os;
}

template<class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
    os << "[";
    REP(i, SZ(v)) {
        if (i) os << ", ";
        os << v[i];
    }
    return os << "]";
}

template<class T1, class T2>
ostream &operator<<(ostream &os, const map<T1, T2> &mp) {
    os << "[";
    for (auto it = mp.begin(); it != mp.end(); ++it) {
        if (it != mp.begin()) {
            os << ", ";
        }
        os << *it;
    }
    return os << "]";
}

// edit
using Int = ll;

template<typename T = int,
        typename E = int,
        typename F = function<T(T, E)>,
        typename Compare = function<bool(T, T) >>
class Dijkstra {
public:
    Int N;
    T s_value;
    T init_value;
    F f;
    Compare cmp;

    vector<T> dist;
    vector<vector<pair<int, E>>>
            G; // first : index, second : E


    Dijkstra(Int N, T init_value = INF, T s_value = 0,
             F f = [](T l, E r) { return l + r; },
             Compare cmp = [](T l, T r) { return l > r; }
    ) : N(N), s_value(s_value), init_value(init_value), f(f), cmp(cmp) {
        dist.resize(N, init_value);
        G.resize(N);
    }

    void add_edge(int f, int t, E e) {
        G[f].push_back(make_pair(t, e));
    }

    void compute(int s) {
        using P = pair<T, int>;
        auto pq_cmp = [this](P l, P r) -> bool {
            return cmp(l.first, r.first);
        };
        priority_queue<P, vector<P>, decltype(pq_cmp)> que(pq_cmp);
        fill(dist.begin(), dist.end(), init_value);
        dist[s] = s_value;

        que.push(P(dist[s], s));

        while (!que.empty()) {
            P p = que.top();
            que.pop();
            int v = p.second;

//            if (!cmp(dist[v], p.first) && (dist[v] != p.first)) continue;
            if (cmp(p.first, dist[v])) continue;

            for (int i = 0; i < G[v].size(); i++) {
                int to_idx = G[v][i].first;
                E to_e = G[v][i].second;

                if (cmp(dist[to_idx], f(dist[v], to_e)) && !(dist[to_idx] == init_value && dist[v] == init_value)) {
                    dist[to_idx] = f(dist[v], to_e);
                    que.push(P(dist[to_idx], to_idx));
                }
            }
        }
    }

    T get_dist(int v) {
        return dist[v];
    }

};

bool solve() {

    int N, M, C, S, G;
    cin >> N >> M >> C >> S >> G;
    if (N == 0) return false;
//    vector<tuple<int, int, int, int>> edges;
    vector<vector<tuple<int, int, int>>> edges(C);
    vector<int> p(C);
    vector<vector<ll>> q(C);
    vector<vector<ll>> r(C);
    REP(i, M) {
        int x, y, d, c;
        cin >> x >> y >> d >> c;
//        edges.emplace_back(x, y, d, c);
        x--, y--, c--;
        edges[c].emplace_back(x, y, d);
    }

    REP(i, C) cin >> p[i];
    REP(i, C) {
        q[i].resize(p[i] - 1);
        r[i].resize(p[i]);
        REP(j, p[i] - 1) cin >> q[i][j];
        q[i].push_back(LINF);

        REP(j, p[i]) cin >> r[i][j];
    }

    Dijkstra<ll, ll> dij(N * C, LINF);
    auto conv = [C](int v, int c) {
        return v * C + c;
    };

    for (int i = 0; i < N; ++i) {
        for (int c = 0; c + 1 < C; ++c) {
            dij.add_edge(conv(i, c), conv(i, c + 1), 0);
            dij.add_edge(conv(i, c + 1), conv(i, c), 0);
        }
    }

    for (int c = 0; c < C; ++c) {
        vector<vector<ll>> dist(N, vector<ll>(N, LINF));
        REP(i, N) dist[i][i] = 0;
        for (auto tup : edges[c]) {
            int x, y;
            ll d;
            tie(x, y, d) = tup;
            chmin(dist[x][y], d);
            chmin(dist[y][x], d);
//            dist[x][y] = dist[y][x] = d;
        }

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

        for (int i = 0; i < N; ++i) {
            for (int j = i + 1; j < N; ++j) {
                if (dist[i][j] == LINF) continue;

                ll d = dist[i][j];
                ll x = 0;
                ll cost = 0;
                int div = 0;

                while (x < d) {
                    ll add = min<ll>(d - x, q[c][div] - x);
                    cost += add * r[c][div];
                    x += add;
                    div++;
                }

                dij.add_edge(conv(i, c), conv(j, c), cost);
                dij.add_edge(conv(j, c), conv(i, c), cost);
            }
        }
    }

    int start = conv(S - 1, 0);
    int goal = conv(G - 1, 0);

    dij.compute(start);

    ll ans = dij.get_dist(goal);
    if (ans == LINF) {
        cout << -1 << endl;
    } else {
        cout << ans << endl;
    }
    if (ans == 30) {
        int a = 0;
    }


    return true;
}


int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
//    std::ifstream in("input.txt");
//    std::cin.rdbuf(in.rdbuf());


    while (solve()) {

    }

    return 0;
}



Measured memory_bytes: 9316