import java.io.*; import java.util.*; public class Maarten { public static void main(String[] args) { Scanner sc = new Scanner(new BufferedReader(new InputStreamReader(System.in))); new Maarten().run(sc); sc.close(); } public void run(Scanner sc) { int n = sc.nextInt(); int m = sc.nextInt(); int t = sc.nextInt(); Map> edges = new HashMap<>(); for (int i = 0; i < m; i++) { int a = sc.nextInt(), b = sc.nextInt(), d = sc.nextInt(), v = sc.nextInt(); edges.putIfAbsent(a, new ArrayList<>()); edges.get(a).add(new Edge(a, b, d, v)); edges.putIfAbsent(b, new ArrayList<>()); edges.get(b).add(new Edge(b, a, d, v)); } if (dijkstra(edges, n, 0) <= t) { System.out.println(0); return; } double low = 0, high = 1e15; while (low * (1. + 1e-15) < high) { double mid = (low + high) / 2; if (dijkstra(edges, n, mid) <= t) high = mid; else low = mid; } System.out.println(high); } private double dijkstra(Map> edges, int n, double overSpeed) { double[] distances = new double[n + 1]; Arrays.fill(distances, 2, n + 1, 1e18); boolean[] done = new boolean[n + 1]; PriorityQueue pq = new PriorityQueue<>(Comparator.comparing(e -> e.dist)); pq.add(new Edge(1, 0)); while (!pq.isEmpty()) { Edge current = pq.poll(); if (current.to == n) return distances[n]; if (done[current.to]) continue; done[current.to] = true; for (Edge e : edges.get(current.to)) { double newDistance = distances[current.to] + e.dist / (e.speed + overSpeed); if (newDistance < distances[e.to]) { distances[e.to] = newDistance; pq.add(new Edge(e.to, newDistance)); } } } return Double.NaN; // Should never happen } static class Edge { public final int from; public final int to; public final double dist; public final double speed; Edge(int to, double dist) { this.from = -1; this.to = to; this.dist = dist; this.speed = -1; } Edge(int from, int to, int dist, int speed) { this.from = from; this.to = to; this.dist = dist; this.speed = speed; } } }