結果

問題 No.654 Air E869120
ユーザー 夕叢霧香(ゆうむらきりか)夕叢霧香(ゆうむらきりか)
提出日時 2018-02-23 23:38:17
言語 C++17
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 6 ms / 2,000 ms
コード長 8,111 bytes
コンパイル時間 1,448 ms
コンパイル使用メモリ 112,296 KB
実行使用メモリ 6,944 KB
最終ジャッジ日時 2024-04-18 11:02:49
合計ジャッジ時間 2,673 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 2 ms
6,944 KB
testcase_02 AC 2 ms
6,944 KB
testcase_03 AC 2 ms
6,944 KB
testcase_04 AC 1 ms
6,940 KB
testcase_05 AC 1 ms
6,944 KB
testcase_06 AC 2 ms
6,940 KB
testcase_07 AC 2 ms
6,940 KB
testcase_08 AC 2 ms
6,944 KB
testcase_09 AC 2 ms
6,940 KB
testcase_10 AC 6 ms
6,944 KB
testcase_11 AC 6 ms
6,940 KB
testcase_12 AC 5 ms
6,940 KB
testcase_13 AC 6 ms
6,944 KB
testcase_14 AC 5 ms
6,940 KB
testcase_15 AC 6 ms
6,940 KB
testcase_16 AC 6 ms
6,940 KB
testcase_17 AC 6 ms
6,944 KB
testcase_18 AC 6 ms
6,944 KB
testcase_19 AC 6 ms
6,944 KB
testcase_20 AC 6 ms
6,940 KB
testcase_21 AC 6 ms
6,944 KB
testcase_22 AC 6 ms
6,940 KB
testcase_23 AC 5 ms
6,940 KB
testcase_24 AC 6 ms
6,944 KB
testcase_25 AC 6 ms
6,944 KB
testcase_26 AC 6 ms
6,940 KB
testcase_27 AC 6 ms
6,940 KB
testcase_28 AC 6 ms
6,940 KB
testcase_29 AC 5 ms
6,940 KB
testcase_30 AC 5 ms
6,940 KB
testcase_31 AC 5 ms
6,940 KB
testcase_32 AC 5 ms
6,940 KB
testcase_33 AC 6 ms
6,940 KB
testcase_34 AC 6 ms
6,944 KB
testcase_35 AC 2 ms
6,940 KB
testcase_36 AC 2 ms
6,944 KB
testcase_37 AC 2 ms
6,940 KB
testcase_38 AC 2 ms
6,940 KB
testcase_39 AC 2 ms
6,944 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include<algorithm>
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
#include<map>
#include<cassert>
using namespace std;
typedef long long lint;
typedef vector<int>vi;
typedef pair<int,int>pii;
#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<Dinic> bm
 * を
 * Benchmark<Dinic, MyDinic> 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<vector<E> > 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<int> 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<int> 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<vector<E> > 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<int> level, iter;
    vector<int> blocked;
    vector<int> unbalance[2]; // { unblocked, blocked }
    vector<int> inS;
    vector<Cap> 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<int> q(n);
        vector<int> 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<int,pii> pipii;
map<pipii,int> 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<pii> leave[A];
vector<pii> arrive[A];

int u[A],v[A],p[A],q[A],w[A];

int main(){
  int n,m,d;
  cin>>n>>m>>d;
  vector<pii>test;
  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<<flow<<endl;
}
0