Problem:
Score : 500 points

Problem Statement

There are N cities numbered 1 to N, connected by M railroads.

You are now at City 1, with 10^{100} gold coins and S silver coins in your pocket.

The i-th railroad connects City U_i and City V_i bidirectionally, and a one-way trip costs A_i silver coins and takes B_i minutes.
You cannot use gold coins to pay the fare.

There is an exchange counter in each city. At the exchange counter in City i, you can get C_i silver coins for 1 gold coin.
The transaction takes D_i minutes for each gold coin you give.
You can exchange any number of gold coins at each exchange counter.

For each t=2, ..., N, find the minimum time needed to travel from City 1 to City t. You can ignore the time spent waiting for trains.

Constraints

2 \leq N \leq 50

N-1 \leq M \leq 100

0 \leq S \leq 10^9

1 \leq A_i \leq 50

1 \leq B_i,C_i,D_i \leq 10^9

1 \leq U_i < V_i \leq N

There is no pair i, j(i \neq j) such that (U_i,V_i)=(U_j,V_j).

Each city t=2,...,N can be reached from City 1 with some number of railroads.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M S
U_1 V_1 A_1 B_1
:
U_M V_M A_M B_M
C_1 D_1
:
C_N D_N

Output

For each t=2, ..., N in this order, print a line containing the minimum time needed to travel from City 1 to City t.

Sample Input 1

3 2 1
1 2 1 2
1 3 2 4
1 11
1 2
2 5

Sample Output 1

2
14

The railway network in this input is shown in the figure below.

In this figure, each city is labeled as follows:

The first line: the ID number i of the city (i for City i)

The second line: C_i / D_i

Similarly, each railroad is labeled as follows:

The first line: the ID number i of the railroad (i for the i-th railroad in input)

The second line: A_i / B_i

You can travel from City 1 to City 2 in 2 minutes, as follows:

Use the 1-st railroad to move from City 1 to City 2 in 2 minutes.

You can travel from City 1 to City 3 in 14 minutes, as follows:

Use the 1-st railroad to move from City 1 to City 2 in 2 minutes.

At the exchange counter in City 2, exchange 3 gold coins for 3 silver coins in 6 minutes.

Use the 1-st railroad to move from City 2 to City 1 in 2 minutes.

Use the 2-nd railroad to move from City 1 to City 3 in 4 minutes.

Sample Input 2

4 4 1
1 2 1 5
1 3 4 4
2 4 2 2
3 4 1 1
3 1
3 1
5 2
6 4

Sample Output 2

5
5
7

The railway network in this input is shown in the figure below:

You can travel from City 1 to City 4 in 7 minutes, as follows:

At the exchange counter in City 1, exchange 2 gold coins for 6 silver coins in 2 minutes.

Use the 2-nd railroad to move from City 1 to City 3 in 4 minutes.

Use the 4-th railroad to move from City 3 to City 4 in 1 minutes.

Sample Input 3

6 5 1
1 2 1 1
1 3 2 1
2 4 5 1
3 5 11 1
1 6 50 1
1 10000
1 3000
1 700
1 100
1 1
100 1

Sample Output 3

1
9003
14606
16510
16576

The railway network in this input is shown in the figure below:

You can travel from City 1 to City 6 in 16576 minutes, as follows:

Use the 1-st railroad to move from City 1 to City 2 in 1 minute.

At the exchange counter in City 2, exchange 3 gold coins for 3 silver coins in 9000 minutes.

Use the 1-st railroad to move from City 2 to City 1 in 1 minute.

Use the 2-nd railroad to move from City 1 to City 3 in 1 minute.

At the exchange counter in City 3, exchange 8 gold coins for 8 silver coins in 5600 minutes.

Use the 2-nd railroad to move from City 3 to City 1 in 1 minute.

Use the 1-st railroad to move from City 1 to City 2 in 1 minute.

Use the 3-rd railroad to move from City 2 to City 4 in 1 minute.

At the exchange counter in City 4, exchange 19 gold coins for 19 silver coins in 1900 minutes.

Use the 3-rd railroad to move from City 4 to City 2 in 1 minute.

Use the 1-st railroad to move from City 2 to City 1 in 1 minute.

Use the 2-nd railroad to move from City 1 to City 3 in 1 minute.

Use the 4-th railroad to move from City 3 to City 5 in 1 minute.

At the exchange counter in City 5, exchange 63 gold coins for 63 silver coins in 63 minutes.

Use the 4-th railroad to move from City 5 to City 3 in 1 minute.

Use the 2-nd railroad to move from City 3 to City 1 in 1 minute.

Use the 5-th railroad to move from City 1 to City 6 in 1 minute.

Sample Input 4

4 6 1000000000
1 2 50 1
1 3 50 5
1 4 50 7
2 3 50 2
2 4 50 4
3 4 50 3
10 2
4 4
5 5
7 7

Sample Output 4

1
3
5

The railway network in this input is shown in the figure below:

Sample Input 5

2 1 0
1 2 1 1
1 1000000000
1 1

Sample Output 5

1000000001

The railway network in this input is shown in the figure below:

You can travel from City 1 to City 2 in 1000000001 minutes, as follows:

At the exchange counter in City 1, exchange 1 gold coin for 1 silver coin in 1000000000 minutes.

Use the 1-st railroad to move from City 1 to City 2 in 1 minute.

Solution in C++ (GCC 9.2.1) (judge verdict: Wrong Answer)

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

template <typename T>
class Graph
{
    void _dfs_toporogical_sort(vector<bool> &visited, const long long n, list<long long> &ret) const
    {
        if (visited[n])
        {
            return;
        }
        visited[n] = true;
        for (auto e : this->edge[n])
        {
            _dfs_toporogical_sort(visited, e.to, ret);
        }
        ret.push_front(n);
    }

    void set_node(const long long N)
    {
        this->node = N + 1;
    }

public:
    struct Edge
    {
        long long to;
        T distance;
        Edge(const long long t, const T d)
        {
            this->to = t;
            this->distance = d;
        }
        bool operator<(const Graph<T>::Edge &e) const
        {
            return this->distance < e.distance;
        }
        bool operator<=(const Graph<T>::Edge &e) const
        {
            return this->distance <= e.distance;
        }
        bool operator>(const Graph<T>::Edge &e) const
        {
            return this->distance > e.distance;
        }
        bool operator>=(const Graph<T>::Edge &e) const
        {
            return this->distance >= e.distance;
        }
        bool operator==(const Graph<T>::Edge &e) const
        {
            return this->distance == e.distance;
        }
    };
    class UnionFind
    {
    public:
        vector<long long> root;

        UnionFind(const long long N)
        {
            this->root = vector<long long>(N + 1, -1);
        }

        long long find_root(const long long A)
        {
            if (this->root[A] < 0)
            {
                return A;
            }
            else
            {
                this->root[A] = find_root(this->root[A]);
            }
            return this->root[A];
        }

        long long size(const long long A)
        {
            return -this->root[find_root(A)];
        }

        bool unite(long long A, long long B)
        {
            A = find_root(A);
            B = find_root(B);
            if (A == B)
            {
                return false;
            }

            if (size(A) < size(B))
            {
                swap(A, B);
            }

            this->root[A] += this->root[B];
            this->root[B] = A;

            return true;
        }

        bool has_same_root(const long long A, const long long B)
        {
            return find_root(A) == find_root(B);
        }
    };
    vector<vector<T>> adjacency_matrix;
    long long node;
    T initial_value;
    vector<vector<Graph<T>::Edge>> edge;

    Graph(const long long N)
    {
        this->set_node(N);
        this->initialize_edge_vector();
    }

    Graph(const long long N, const T init)
    {
        this->set_node(N);
        this->initialize_edge_vector();
        this->set_initial_value(init);
    }

    void set_initial_value(const T init)
    {
        this->initial_value = init;
    }

    void initialize_adjacency_matrix()
    {
        this->adjacency_matrix = vector<vector<T>>(
            this->node, vector<T>(this->node, this->initial_value));
    }

    void initialize_adjacency_matrix(const T init)
    {
        this->set_initial_value(init);
        this->initialize_adjacency_matrix();
    }

    void initialize_edge_vector()
    {
        this->edge = vector<vector<Graph<T>::Edge>>(this->node);
    }

    void update_adjacency_matrix(const long long from, const long long to, const T distance = 1)
    {
        this->adjacency_matrix[from][to] = distance;
    }

    void add_edge(const long long from, const long long to, const T distance = 1)
    {
        this->edge[from].push_back({to, distance});
    }

    // O(V^3)
    // CAUTION: Use adjacency matrix
    vector<vector<T>> run_floyd_warshall() const
    {
        vector<vector<T>> ret(this->adjacency_matrix);
        for (long long i = 0; i < this->node; i++)
        {
            for (long long j = 0; j < this->node; j++)
            {
                for (long long k = 0; k < this->node; k++)
                {
                    ret[j][k] = min(ret[j][k], ret[j][i] + ret[i][k]);
                }
            }
        }
        return ret;
    }

    // O(E)
    // CAUTION: Non-weighted only
    // CAUTION: Use edge vector
    vector<T> run_bfs(const long long from) const
    {
        vector<T> distance(this->node, this->initial_value);
        vector<bool> visited(this->node, false);
        queue<long long> q;
        q.push(from);
        for (long long i = 0; i < this->node && !q.empty(); i++)
        {
            queue<long long> tmp;
            while (!q.empty())
            {
                if (visited[q.front()])
                {
                    q.pop();
                    continue;
                }
                distance[q.front()] = i;
                visited[q.front()] = true;
                for (Graph<T>::Edge e : this->edge[q.front()])
                {
                    if (visited[e.to])
                    {
                        continue;
                    }
                    tmp.push(e.to);
                }
                q.pop();
            }
            q = tmp;
        }
        return distance;
    }

    // O(VE)
    // CAUTION: Use edge vector
    vector<T> run_bellman_ford(const long long from) const
    {
        vector<T> distance(this->node, this->initial_value);
        distance[from] = 0;

        for (long long i = 0; i < this->node - 1; i++)
        {
            for (long long j = 0; j < this->node; j++)
            {
                for (Graph<T>::Edge e : this->edge[j])
                {
                    if (distance[e.to] > distance[j] + e.distance)
                    {
                        distance[e.to] = distance[j] + e.distance;
                    }
                }
            }
        }
        return distance;
    }

    // O(E + VlogV)
    // CAUTION: Use edge vector
    // CAUTION: Node-indices must be [1, N]
    vector<T> run_dijkstra(const long long from) const
    {
        vector<T> distance(this->node, this->initial_value);
        priority_queue<Graph<T>::Edge, vector<Graph<T>::Edge>, greater<Graph<T>::Edge>> queue;
        queue.push(Graph<T>::Edge(from, 0));
        for (long long i = 1; i < this->node && !queue.empty(); i++)
        {
            T d = queue.top().distance;
            long long to = queue.top().to;
            queue.pop();
            if (distance[to] == this->initial_value)
            {
                distance[to] = d;
                for (Graph<T>::Edge e : this->edge[to])
                {
                    if (distance[e.to] == this->initial_value)
                    {
                        queue.push({e.to, e.distance + d});
                    }
                }
            }
            else
            {
                i--;
            }
        }
        return distance;
    }

    // O(ElogV)
    // CAUTION: Use edge vector
    // CAUTION: Node-indices must be [1, N]
    T run_prim() const
    {
        vector<bool> is_visited(this->node, false);
        T cost = 0;
        priority_queue<Graph<T>::Edge, vector<Graph<T>::Edge>, greater<Graph<T>::Edge>> queue;
        queue.push(Graph<T>::Edge(1, 0));
        for (long long i = 1; i < this->node && !queue.empty(); i++)
        {
            T distance = queue.top().distance;
            long long to = queue.top().to;
            queue.pop();
            if (is_visited[to])
            {
                i--;
            }
            else
            {
                cost += distance;
                is_visited[to] = true;
                for (Graph<T>::Edge e : this->edge[to])
                {
                    queue.push({e.to, e.distance});
                }
            }
        }
        return cost;
    }

    // O(ElogV)
    // CAUTION: Use edge vector
    T run_kruskal() const
    {
        T cost = 0;
        vector<pair<Graph<T>::Edge, long long>> edge_from;
        for (long long i = 0; i < this->node; i++)
        {
            for (auto e : this->edge[i])
            {
                edge_from.push_back(make_pair(e, i));
            }
        }
        sort(edge_from.begin(), edge_from.end());

        Graph<T>::UnionFind uf(this->node);
        for (pair<Graph<T>::Edge, long long> e_f : edge_from)
        {
            auto e = e_f.first;
            long long from = e_f.second;
            if (!uf.has_same_root(from, e.to))
            {
                uf.unite(from, e.to);
                cost += e.distance;
            }
        }
        return cost;
    }

    // O(V)
    // CAUTION: Without cycle only
    // CAUTION: Use edge vector
    vector<long long> run_toporogical_sort() const
    {
        list<long long> ret_list;
        vector<bool> visited(this->node, false);
        for (long long i = 0; i < this->node; i++)
        {
            _dfs_toporogical_sort(visited, i, ret_list);
        }

        vector<long long> ret(ret_list.begin(), ret_list.end());
        return ret;
    }
};

int main()
{
    constexpr long long MAX_SILVER = 50 * 50;
    long long N, M, S;
    cin >> N >> M >> S;
    S = min(S, MAX_SILVER - 1);

    Graph<pair<long long, long long>> g(N);
    long long U, V, A, B;
    for (long long i = 0; i < M; i++)
    {
        cin >> U >> V >> A >> B;
        g.add_edge(U, V, make_pair(-A, B));
        g.add_edge(V, U, make_pair(-A, B));
    }

    long long C, D;
    for (long long i = 1; i <= N; i++)
    {
        cin >> C >> D;
        g.add_edge(i, i, make_pair(C, D));
    }

    long long init = LONG_LONG_MAX;
    vector<vector<long long>> ans(N + 1, vector<long long>(MAX_SILVER, init));
    priority_queue<pair<long long, pair<long long, long long>>, vector<pair<long long, pair<long long, long long>>>, greater<pair<long long, pair<long long, long long>>>> q;
    q.push(make_pair(0, make_pair(1, S)));
    for (long long i = 0; i < (N * MAX_SILVER) && !q.empty(); i++)
    {
        long long distance = q.top().first;
        long long to = q.top().second.first;
        long long silver = q.top().second.second;
        q.pop();

        if (ans[to][silver] == init)
        {
            ans[to][silver] = distance;

            for (auto e : g.edge[to])
            {
                long long next_silver = silver + e.distance.first;
                long long next_distance = distance + e.distance.second;
                if (next_silver < 0)
                {
                    continue;
                }
                if (next_silver >= MAX_SILVER)
                {
                    continue;
                }
                q.push(make_pair(next_distance, make_pair(e.to, next_silver)));
            }
        }
    }
    for (long long i = 2; i <= N; i++)
    {
        long long a = init;
        for (long long j = 0; j < MAX_SILVER; j++)
        {
            a = min(a, ans[i][j]);
        }
        cout << a << endl;
    }
}