#include #include #include #include #include #include using namespace std; typedef long long ll; typedef pair P; /**** Const List ****/ #define INF 1000000000 #define LLINF 100000000000000000 /**** Network Flow ****/ #define MAX_FLOW_MAX_V 10000 class MaxFlow { public: struct edge { ll to, cap, rev; }; vector G[MAX_FLOW_MAX_V]; bool used[MAX_FLOW_MAX_V]; ll level[MAX_FLOW_MAX_V]; ll iter[MAX_FLOW_MAX_V]; void init() { for (ll i = 0; i < MAX_FLOW_MAX_V; i++) { G[i].clear(); } } void add_edge(ll from, ll to, ll cap) { G[from].push_back((edge){to, cap, (ll)G[to].size()}); G[to].push_back((edge){from, 0, (ll)G[from].size() - 1}); } void add_undirected_edge(ll e1, ll e2, ll cap) { G[e1].push_back((edge){e2, cap, (ll)G[e2].size()}); G[e2].push_back((edge){e1, cap, (ll)G[e1].size() - 1}); } ll dfs(ll v, ll t, ll f) { if (v == t) return f; used[v] = true; for (ll i = 0; i < (ll)G[v].size(); i++) { edge &e = G[v][i]; if (!used[e.to]&& e.cap > 0) { ll d = dfs(e.to, t, min(f, e.cap)); if (d > 0) { e.cap -= d; G[e.to][e.rev].cap += d; return d; } } } return 0; } ll max_flow(ll s, ll t) { ll flow = 0; while (1) { memset(used, 0, sizeof(used)); ll f = dfs(s, t, INF); if (f == 0) return flow; flow += f; } } void bfs(ll s) { memset(level, -1, sizeof(level)); queue que; level[s] = 0; que.push(s); while (!que.empty()) { ll v = que.front(); que.pop(); for (ll i = 0; i < (ll)G[v].size(); i++) { edge &e = G[v][i]; if (e.cap > 0 && level[e.to] < 0) { level[e.to] = level[v] + 1; que.push(e.to); } } } } ll dinic_dfs(ll v, ll t, ll f) { if (v == t) return f; for (ll &i= iter[v]; i < (ll)G[v].size(); i++) { edge &e = G[v][i]; if (e.cap > 0 && level[v] < level[e.to]) { ll d = dinic_dfs(e.to, t, min(f, e.cap)); if (d > 0) { e.cap -= d; G[e.to][e.rev].cap += d; return d; } } } return 0; } ll dinic(ll s, ll t) { ll flow = 0; while (1) { bfs(s); if (level[t] < 0) return flow; memset(iter, 0, sizeof(iter)); ll f; while ((f = dinic_dfs(s, t, INF)) > 0) { flow += f; } } } }; /**** bipartite matching ****/ #define BIPARTITE_MATCHING_MAX_V 10000 class BipartiteMatching { public: int V; vector G[BIPARTITE_MATCHING_MAX_V]; int match[BIPARTITE_MATCHING_MAX_V]; bool used[BIPARTITE_MATCHING_MAX_V]; BipartiteMatching(int v) { V = v; } void init(int v) { V = v; for (int i = 0; i < BIPARTITE_MATCHING_MAX_V; i++) { G[i].clear(); } } void add_edge(int u, int v) { G[u].push_back(v); G[v].push_back(u); } bool dfs(int v) { used[v] = true; for (int i = 0; i < (int)G[v].size(); i++) { int u = G[v][i], w = match[u]; if (w < 0 || !used[w] && dfs(w)) { match[v] = u; match[u] = v; return true; } } return false; } int max_matching() { int res = 0; memset(match, -1, sizeof(match)); for (int v = 0; v < V;v++) { if (match[v] < 0) { memset(used, 0, sizeof(used)); if (dfs(v)) { res++; } } } return res; } }; #define MIN_COST_FLOW_MAX_V 10000 class MinCostFlow { public: struct edge { int to, cap, cost, rev; }; int V; vector G[MIN_COST_FLOW_MAX_V]; int dist[MIN_COST_FLOW_MAX_V]; int prevv[MIN_COST_FLOW_MAX_V]; int preve[MIN_COST_FLOW_MAX_V]; MinCostFlow(int v) { V = v; } void init() { for (int i = 0; i < MAX_FLOW_MAX_V; i++) { G[i].clear(); } } void add_edge(int from, int to, int cap, int cost) { G[from].push_back((edge){to, cap, cost, (int)G[to].size()}); G[to].push_back((edge){from, 0, -cost, (int)G[from].size() - 1}); } void add_undirected_edge(int e1, int e2, int cap, int cost) { add_edge(e1, e2, cap, cost); add_edge(e2, e1, cap, cost); } int min_cost_flow(int s, int t, int f) { // minas int res = 0; while (f > 0) { fill(dist, dist + V, INF); dist[s] = 0; bool update = true; while (update) { update = false; for (int v = 0; v < V; v++) { if (dist[v] == INF) continue; for (int i = 0; i < (int)G[v].size(); i++) { edge &e = G[v][i]; if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) { dist[e.to] = dist[v] + e.cost; prevv[e.to] = v; preve[e.to] = i; update = true; } } } } if (dist[t] == INF) { return -1; } int d = f; for (int v = t; v != s; v = prevv[v]) { d = min(d, G[prevv[v]][preve[v]].cap); } f -= d; res += d * dist[t]; for (int v = t; v != s; v = prevv[v]) { edge &e = G[prevv[v]][preve[v]]; e.cap -= d; G[v][e.rev].cap += d; } } return res; } int min_cost_flow_dijkstra(int s, int t, int f) { int res = 0; //fill(h, h + V, 0); while (f > 0) { priority_queue, greater

> que; //fill(dist, // あとで書く } return 0; } }; ll n, m, d; ll u[1000], v[1000], p[1000], q[1000], w[1000]; vector E[1000]; ll num[1000], endnum; MaxFlow f; int main() { scanf("%lld%lld%lld", &n, &m, &d); for (ll i = 0; i < m; i++) { scanf("%lld%lld%lld%lld%lld", &u[i], &v[i], &p[i], &q[i], &w[i]); u[i]--; v[i]--; E[u[i]].push_back(p[i]); } ll temp = 0; for (ll i = 0; i < n; i++) { num[i] = temp; temp += (ll)E[i].size(); sort(E[i].begin(), E[i].end()); } endnum = temp + 1; for (ll i = 0; i < m; i++) { ll from = u[i], to = v[i], time = q[i] + d; ll size = (ll)E[to].size(), j, fromnumber = 0; while (E[from][fromnumber] != p[i]) fromnumber++; fromnumber += num[from]; if (to == n - 1) { f.add_edge(fromnumber, endnum, w[i]); continue; } if (size == 0) continue; if (time > E[to][size - 1]) continue; for (j = 0; j < size; j++) { if (time <= E[to][j]) break; } ll tonumber = j + num[to]; f.add_edge(fromnumber, tonumber, w[i]); } for (ll i = 0; i < n; i++) { ll size = (ll)E[i].size(); for (ll j = 0; j < size - 1; j++) { f.add_edge(num[i] + j, num[i] + j + 1, LLINF); } } printf("%lld\n", f.dinic(0, endnum)); }