#include #include #include #include #include #include #include using namespace std; typedef long long lint; typedef vectorvi; typedef pairpii; #define rep(i,n)for(int i=0;i<(int)(n);++i) // https://gist.github.com/MiSawa/9645253 #define REP(i, b, n) for(int i = (b); i < (n); ++i) #define let(v, x) __typeof(x) v = (x) #define foreach(i,v) for(let(i, (v).begin());i!=(v).end();i++) /** * 割とどうしてくれてもいいけど, 理解 && バグ潰ししてから使うべきです. * */ /** * Dinic と同じように, * - 頂点数を取るコンストラクタ * - add_edge(src, dst, cap) * - run(s, t) * の 3 つを備えるクラス (例えば MyDinic) を作って, * * Benchmark bm * を * Benchmark bm * とかに変えれば, 比較出来る. */ struct Dinic{//{{{ typedef lint Cap; static const Cap INF = 1e16; struct E{//{{{ int dst; Cap cap; int rev; E(int dst, Cap cap, int rev) : dst(dst), cap(cap), rev(rev) {} };//}}} int n; vector > g; Dinic(int n) : n(n), g(n) {} inline void add_edge(int src, int dst, Cap cap){//{{{ if(src == dst) return; g[src].push_back(E(dst,cap,g[dst].size())); g[dst].push_back(E(src, 0 ,g[src].size() - 1)); }//}}} inline void add_undirected_edge(int src, int dst, Cap cap){//{{{ if(src == dst) return; g[src].push_back(E(dst,cap,g[dst].size())); g[dst].push_back(E(src,cap,g[src].size() - 1)); }//}}} vector level, iter; Cap dfs(const int &s, const int &u, Cap crr){//{{{ if(s == u || crr == 0) return crr; Cap sum = 0; for(int &i = iter[u]; i < g[u].size(); ++i){ E &e = g[u][i], &ee = g[e.dst][e.rev]; const int &v = e.dst; // s -- v - u -- t if(level[v] >= level[u] || ee.cap <= 0) continue; Cap f = dfs(s, v, min(crr - sum, ee.cap)); if(f <= 0) continue; ee.cap -= f; e.cap += f; sum += f; if(sum == crr) break; } return sum; }//}}} Cap run(int s, int t){//{{{ vector q(n); for(Cap flow = 0; ;){ level.assign(n, -1); int ql = 0, qr = 0; level[q[qr++] = s] = 0; while(ql != qr && level[t] == -1){ int u = q[ql++]; foreach(e, g[u]) if(e->cap > 0 && level[e->dst] == -1) level[ q[qr++] = e->dst ] = level[u] + 1; } if(level[t] == -1) return flow; iter.assign(n, 0); flow += dfs(s, t, INF); } }//}}} };//}}} struct Wave{//{{{ typedef lint Cap; static const Cap INF = 1e16; struct E{//{{{ int src, dst; Cap cap, _cap; int rev; E(int src, int dst, Cap cap, int rev) : src(src), dst(dst), cap(cap), _cap(0), rev(rev) {} };//}}} int n; vector > g; Wave(int n) : n(n), g(n) {} inline void add_edge(int src, int dst, Cap cap){//{{{ if(src == dst) return; g[src].push_back(E(src, dst,cap,g[dst].size())); g[dst].push_back(E(dst, src, 0 ,g[src].size() - 1)); }//}}} inline E &rev(const E& e){ return g[e.dst][e.rev]; } vector level, iter; vector blocked; vector unbalance[2]; // { unblocked, blocked } vector inS; vector ex; inline void push(E &e){//{{{ Cap f = min(e.cap, ex[e.src]); if(!inS[e.dst]) unbalance[blocked[e.dst]].push_back(e.dst); inS[e.dst] = true; e.cap -= f; rev(e).cap += f; ex[e.src] -= f; ex[e.dst] += f; }//}}} // dir = +1 ? s to t : t to s inline void discharge(const int& u, const int dir){//{{{ for(int &i = iter[u]; i < g[u].size(); ++i){ E &e = g[u][i]; if(e.cap == 0 || level[e.src] + dir != level[e.dst]) continue; if(dir == +1 && blocked[e.dst]) continue; push(e); if(ex[u] == 0) return; } blocked[u] = true; if(!inS[u]) unbalance[1].push_back(u); inS[u] = true; iter[u] = 0; }//}}} Cap run(int s, int t){//{{{ vector q(n); vector tmp; tmp.reserve(n); rep(i, 2) unbalance[i].reserve(n); rep(i, 2) unbalance[i].clear(); inS.assign(n, false); inS[s] = inS[t] = true; for(Cap flow = 0; ;){ level.assign(n, -1); int ql = 0, qr = 0; level[q[qr++] = s] = 0; while(ql != qr && level[t] == -1){ const int &u = q[ql++]; foreach(e, g[u]) if(level[e->dst] == -1 && e->cap + e->_cap > 0) level[ q[qr++] = e->dst ] = level[u] + 1; } if(level[t] == -1) return flow; rep(i, qr){ if(level[q[i]] == level[t] && q[i] != t){ level[q[i]] = -1; continue; } foreach(e, g[q[i]]){ if(level[e->src] + 1 == level[e->dst]){ e->cap += e->_cap; e->_cap = 0; }else{ e->_cap += e->cap; e->cap = 0; } } } iter.assign(n, 0); blocked.assign(n, false); ex.assign(n, 0); ex[s] = INF; discharge(s, +1); ex[s] = 0; while(!unbalance[0].empty() || !unbalance[1].empty()){ rep(b, 2) while(!unbalance[b].empty()){ tmp.clear(); int l = level[unbalance[b].back()]; while(!unbalance[b].empty() && level[unbalance[b].back()] == l){ int v = unbalance[b].back(); unbalance[b].pop_back(); inS[v] = false; tmp.push_back(v); } foreach(v, tmp) discharge(*v, b ? -1 : +1); } } flow += ex[t]; } }//}}} };//}}} const lint INF=1e16; typedef pair pipii; map memo; int get(int v,pii t){ pipii ind(v,t); if(memo.count(ind))return memo[ind]; int s=memo.size(); memo[ind]=s; return s; } const int A=1000; vector leave[A]; vector arrive[A]; int u[A],v[A],p[A],q[A],w[A]; int main(){ int n,m,d; cin>>n>>m>>d; vectortest; rep(i,m){ cin>>u[i]>>v[i]>>p[i]>>q[i]>>w[i]; u[i]--,v[i]--; leave[u[i]].push_back(pii(p[i],i)); arrive[v[i]].push_back(pii(q[i],i)); test.push_back(pii(p[i],-(i+1))); test.push_back(pii(q[i],i+1)); get(u[i],pii(p[i],i)); get(n+v[i],pii(q[i],i)); } #if 0 sort(test.begin(),test.end()); rep(i,test.size()){ int idx=test[test.size()-1-i].second; int j=abs(idx)-1; if(idx>0){ get(u[j],pii(p[j],j)); } } rep(i,test.size()){ int idx=test[test.size()-1-i].second; int j=abs(idx)-1; if(idx<0){ get(v[j],pii(q[j],j)); } } #endif int tn=memo.size()+2; Dinic din(tn); rep(i,n){ sort(leave[i].begin(),leave[i].end()); sort(arrive[i].begin(),arrive[i].end()); } rep(i,n){ rep(j,leave[i].size()-1){ int a=get(i,leave[i][j]); int b=get(i,leave[i][j+1]); din.add_edge(a,b,INF); } rep(j,arrive[i].size()){ int a=get(n+i,arrive[i][j]); lint time=arrive[i][j].first; lint dst=time+d; if(dst>1e9)continue; int idx=lower_bound(leave[i].begin(),leave[i].end(),pii((int)dst,-1))-leave[i].begin(); if(idx<(int)leave[i].size()){ int b=get(i,leave[i][idx]); din.add_edge(a,b,INF); } } } rep(i,m){ int a=get(u[i],pii(p[i],i)); int b=get(n+v[i],pii(q[i],i)); din.add_edge(a,b,w[i]); } int src=tn-2; int sink=tn-1; rep(i,arrive[n-1].size()){ int a=get(n+n-1,arrive[n-1][i]); din.add_edge(a,sink,INF); } rep(i,leave[0].size()){ int a=get(0,leave[0][i]); din.add_edge(src,a,INF); } lint flow=din.run(src,sink); cout<