import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

public class evacuation_nn_bin1 {

	static class UsedInteger {
		int[] v;
		int current;

		public UsedInteger(int n) {
			v = new int[n];
			clear();
		}

		boolean get(int x) {
			return v[x] == current;
		}

		void set(int x) {
			v[x] = current;
		}

		void clear() {
			++current;
		}
	}

	static class Edge {
		int from;
		int to;
		int flow;
		int cap;
		Edge rev;

		public Edge(int from, int to, int flow, int cap) {
			this.from = from;
			this.to = to;
			this.flow = flow;
			this.cap = cap;
		}

	}

	static class Graph {
		List<List<Edge>> edges;
		UsedInteger used;

		Graph() {
			edges = new ArrayList<>();
		}

		int dfs(int v, int t, int cMin, int mask) {
			if (v == t) {
				return cMin;
			}
			used.set(v);
			List<Edge> ed = edges.get(v);
			for (int index = 0; index < ed.size(); index++) {
				Edge e = ed.get(index);
				if (used.get(e.to) || (e.cap - e.flow & mask) == 0) {
					continue;
				}
				int d = dfs(e.to, t, Math.min(cMin, e.cap - e.flow & mask),
						mask);
				if (d == 0) {
					continue;
				}
				e.flow += d;
				e.rev.flow -= d;
				return d;
			}
			return 0;
		}

		int maxFlow(int source, int target) {
			int mask = 1 << 30;
			int flow = 0;
			used = new UsedInteger(edges.size());
			while (true) {
				while (true) {
					used.clear();
					int add = dfs(source, target, Integer.MAX_VALUE, mask);
					if (add == 0) {
						break;
					}
					flow += add;
				}
				if ((mask & 1) == 1) {
					break;
				}
				mask |= mask >> 1;
			}
			return flow;
		}

		int maxFlow2(int source, int target) {
			int[] q = new int[edges.size()];
			Edge[] lastEdge = new Edge[edges.size()];
			used = new UsedInteger(edges.size());
			int flow = 0;
			while (true) {
				used.clear();
				int head = 0;
				int tail = 0;
				q[tail++] = source;
				used.set(source);
				all: while (head < tail) {
					int v = q[head++];
					List<Edge> ed = edges.get(v);
					for (int i = 0; i < ed.size(); i++) {
						Edge e = ed.get(i);
						if (e.cap == e.flow || used.get(e.to)) {
							continue;
						}
						used.set(e.to);
						lastEdge[e.to] = e;
						q[tail++] = e.to;
						if (e.to == target) {
							break all;
						}
					}
				}
				if (!used.get(target)) {
					break;
				}
				int add = Integer.MAX_VALUE;
				for (int v = target; v != source;) {
					Edge e = lastEdge[v];
					if (e.cap - e.flow < add) {
						add = e.cap - e.flow;
					}
					v = e.from;
				}
				flow += add;
				for (int v = target; v != source;) {
					Edge e = lastEdge[v];
					e.flow += add;
					e.rev.flow -= add;
					v = e.from;
				}
			}
			return flow;
		}

		void addEdge(int from, int to, int cap) {
			Edge e1 = new Edge(from, to, 0, cap);
			Edge e2 = new Edge(to, from, 0, 0);
			e1.rev = e2;
			e2.rev = e1;
			edges.get(from).add(e1);
			edges.get(to).add(e2);
		}

		void addVertices(int v) {
			while (v-- > 0) {
				edges.add(new ArrayList<Edge>(1));
			}
		}
	}

	void solve() throws IOException {
		int n = nextInt();
		int m = nextInt();
		int k = nextInt();
		int limit = nextInt();
		int[] from = new int[m];
		int[] to = new int[m];
		int[] length = new int[m];
		int[] capacity = new int[m];
		for (int i = 0; i < m; i++) {
			from[i] = nextInt() - 1;
			to[i] = nextInt() - 1;
			length[i] = nextInt();
			capacity[i] = nextInt();
		}
		final int INF = 1000000000;
		int left = 0;
		int right = limit + 1;
		int last = 0;
		while (left < right - 1) {
			int mid = left + right >> 1;
			Graph g = new Graph();
			g.addVertices(2);
			int source = 0;
			int target = 1;
			for (int time = 0; time <= mid; time++) {
				g.addVertices(n);
				g.addEdge(source, 2 + time * n, INF);
				for (int i = 0; i < m; i++) {
					if (length[i] > time) {
						continue;
					}
					g.addEdge(2 + from[i] + (time - length[i]) * n, 2 + to[i]
							+ time * n, capacity[i]);
				}
				g.addEdge(2 + time * n + (n - 1), target, INF);
			}
			int got = g.maxFlow(source, target);
			if (got >= k) {
				right = mid;
			} else {
				left = mid;
				last = got;
			}
		}
		if (left == limit) {
			out.println("NO");
			out.println(last);
		} else {
			out.println("YES");
			out.println(right);
		}
	}

	void run() {
		try {
			br = new BufferedReader(new FileReader("evacuation.in"));
			out = new PrintWriter("evacuation.out");
			solve();
			out.close();
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	BufferedReader br;
	PrintWriter out;

	int nextInt() throws IOException {
		int c = br.read();
		while (c < '0' || c > '9') {
			c = br.read();
		}
		int ret = 0;
		while (c >= '0' && c <= '9') {
			ret = ret * 10 + c - '0';
			c = br.read();
		}
		return ret;
	}

	public static void main(String[] args) {
		new evacuation_nn_bin1().run();
	}
}
