#include #include #define rep2(i, k, n) for (i64 i = (i64)(k); i < (i64)(n); i++) #define rep(i, n) rep2(i, 0, n) #define all(x) begin(x), end(x) #ifdef ENV_LOCAL #define dump \ if (1) cerr #else #define dump \ if (0) cerr #endif using namespace std; using namespace std::string_literals; using i32 = int32_t; using i64 = int64_t; using f64 = double; using f80 = long double; using vi32 = vector; using vi64 = vector; // using namespace harudake; using Weight = int; Weight INF = 1000000000; struct Edge { int src, dest; Weight weight; bool operator<(const Edge &rhs) const { return weight > rhs.weight; } }; using Edges = vector; using Graph = vector; using Array = vector; using Matrix = vector; void add_edge(Graph &g, int src, int dest, Weight weight) { g[src].push_back((Edge){src, dest, weight}); g[dest].push_back((Edge){dest, src, weight}); } // Dijkstra (Verified: AOJ2005) void dijkstra(Graph &g, Array &d, int s) { d.assign(g.size(), INF); d[s] = 0; using P = pair; priority_queue, greater

> que; que.push(P(0, s)); while (!que.empty()) { Weight dist = que.top().first; int v = que.top().second; que.pop(); if (d[v] < dist) continue; rep(i, g[v].size()) { Edge e = g[v][i]; if (d[e.dest] > d[v] + e.weight) { d[e.dest] = d[v] + e.weight; que.push(P(d[e.dest], e.dest)); } } } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); i64 n, m, x; cin >> n >> m >> x; vector> edges; rep(i, m) { i64 u, v, a, b; cin >> u >> v >> a >> b; --u; --v; edges.emplace_back(u, v, a, b); } i64 le = -1, gt = 1e9 + 1; while (gt - le > 1) { i64 mid = (gt + le) / 2; Graph g(n); for (auto &&[u, v, a, b] : edges) { if (b < mid) continue; add_edge(g, u, v, a); } Array dist(n); dijkstra(g, dist, 0); if (dist[n - 1] <= x) { le = mid; } else { gt = mid; } } cout << le << endl; return 0; }