結果
| 問題 |
No.654 Air E869120
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2019-12-22 18:31:16 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 36 ms / 2,000 ms |
| コード長 | 8,049 bytes |
| コンパイル時間 | 2,587 ms |
| コンパイル使用メモリ | 181,236 KB |
| 実行使用メモリ | 69,912 KB |
| 最終ジャッジ日時 | 2024-09-14 14:04:36 |
| 合計ジャッジ時間 | 3,846 ms |
|
ジャッジサーバーID (参考情報) |
judge6 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 35 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
// 以下のサイトのものをお借りしています。
// https://kopricky.github.io/code/Academic/max_flow_push_relabel.html
class Stack {
private:
const int N, H;
vector<int> node;
public:
Stack(const int N_, const int H_) : N(N_), H(H_), node(N+H){ clear(); }
inline bool empty(const int h) const { return node[N+h] == N+h; }
inline int top(const int h) const { return node[N+h]; }
inline void pop(const int h){ node[N+h] = node[node[N+h]]; }
inline void push(const int h, const int u){ node[u] = node[N+h], node[N+h] = u; }
inline void clear(){ iota(node.begin() + N, node.end(), N); }
};
class List {
public:
struct node {
int prev, next;
};
const int N, H;
vector<node> dat;
List(const int N_, const int H_) : N(N_), H(H_), dat(N+H){ clear(); }
inline bool empty(const int h) const { return (dat[N+h].next == N+h); }
inline bool more_one(const int h) const { return dat[N+h].prev != dat[N+h].next; }
inline void insert(const int h, const int u){
dat[u].prev = dat[N+h].prev, dat[u].next = N+h;
dat[dat[N+h].prev].next = u, dat[N+h].prev = u;
}
inline void erase(const int u){
dat[dat[u].prev].next = dat[u].next, dat[dat[u].next].prev = dat[u].prev;
}
inline void clear(){
for(int i = N; i < N+H; ++i) dat[i].prev = dat[i].next = i;
}
};
template <typename T> class PushRelabel {
public:
struct edge {
const int to, rev;
T cap;
edge(const int _to, const int _rev, const T _cap) : to(_to), rev(_rev), cap(_cap){}
};
private:
const int V;
int s, t, pot_max, checker;
vector<T> excess;
vector<int> potential, cur_edge, que;
List all_ver;
Stack act_ver;
int calc_active(){
pot_max = -1;
for(int i = 0; i < V; ++i){
if(potential[i] < V){
cur_edge[i] = 0;
pot_max = max(potential[i], pot_max);
all_ver.insert(potential[i], i);
if(excess[i] > 0 && i != t) act_ver.push(potential[i], i);
}else{
potential[i] = V+1;
}
}
return pot_max;
}
void bfs(){
for(int i = 0; i < V; ++i) potential[i] = max(potential[i], V);
potential[t] = 0;
int qh = 0, qt = 0;
for(que[qt++] = t; qh++ < qt;){
int u = que[qh - 1];
for(const edge& e : G[u]){
if(potential[e.to] == V && G[e.to][e.rev].cap > 0){
potential[e.to] = potential[u] + 1, que[qt++] = e.to;
}
}
}
}
int init(){
potential[s] = V + 1;
bfs();
for(edge& e : G[s]){
if(potential[e.to] < V){
G[e.to][e.rev].cap = e.cap, excess[s] -= e.cap, excess[e.to] += e.cap;
e.cap = 0;
}
}
return calc_active();
}
int global_relabel(){
bfs();
all_ver.clear(), act_ver.clear();
return calc_active();
}
void gap_relabel(const int u){
for(int i = potential[u]; i <= pot_max; ++i){
for(int id = all_ver.dat[V+i].next; id < V; id = all_ver.dat[id].next){
potential[id] = V + 1;
}
all_ver.dat[V+i].prev = all_ver.dat[V+i].next = V + i;
}
}
int discharge(const int u){
for(int& i = cur_edge[u]; i < (int)G[u].size(); ++i){
edge& e = G[u][i];
if(potential[u] == potential[e.to] + 1 && e.cap > 0){
if(push(u, e)) return potential[u];
}
}
return relabel(u);
}
bool push(const int u, edge& e){
T f = min(e.cap, excess[u]);
const int v = e.to;
e.cap -= f, excess[u] -= f;
G[v][e.rev].cap += f, excess[v] += f;
if(excess[v] == f && v != t) act_ver.push(potential[v], v);
return (excess[u] == 0);
}
int relabel(const int u){
++checker;
int prv = potential[u], cur = V;
for(int i = 0; i < (int)G[u].size(); ++i){
const edge& e = G[u][i];
if(cur > potential[e.to] + 1 && e.cap > 0){
cur_edge[u] = i;
cur = potential[e.to] + 1;
}
}
if(all_ver.more_one(prv)){
all_ver.erase(u);
if((potential[u] = cur) == V) return potential[u] = V+1, prv;
act_ver.push(cur, u);
all_ver.insert(cur, u);
pot_max = max(pot_max, cur);
}else{
gap_relabel(u);
return pot_max = prv - 1;
}
return cur;
}
int validate_discharge(const int u){
for(int& i = cur_edge[u]; i < (int)G[u].size(); ++i){
edge& e = G[u][i];
if(potential[u] == potential[e.to] + 1 && e.cap > 0){
if(validate_push(u, e)) return potential[u] - V;
}
}
return validate_relabel(u);
}
bool validate_push(const int u, edge& e){
T f = min(e.cap, excess[u]);
const int v = e.to;
e.cap -= f, excess[u] -= f;
G[v][e.rev].cap += f, excess[v] += f;
if(excess[v] == f) act_ver.push(potential[v] - V, v);
return (excess[u] == 0);
}
int validate_relabel(const int u){
int cur = 2 * V;
for(int i = 0; i < (int)G[u].size(); ++i){
const edge& e = G[u][i];
if(cur > potential[e.to] + 1 && e.cap > 0){
cur_edge[u] = i;
cur = potential[e.to] + 1;
}
}
potential[u] = cur;
act_ver.push(cur - V, u);
return cur - V;
}
void validate(){
for(int i = 0; i < V; ++i){
if(potential[i] >= V){
cur_edge[i] = 0, potential[i] = V;
if(excess[i] > 0) act_ver.push(0, i);
}
}
int level = 0;
while(level >= 0){
if(act_ver.empty(level)){
--level;
continue;
}
int u = act_ver.top(level);
act_ver.pop(level);
level = validate_discharge(u);
}
}
public:
vector<vector<edge> > G;
PushRelabel(const int node_size)
: V(node_size), pot_max(-1), checker(0), excess(V, (T)0),
potential(V, 0), cur_edge(V), que(V), all_ver(V, V), act_ver(V, V), G(V){}
void add_edge(const int _from, const int _to, const T _cap){
G[_from].emplace_back(_to, (int)G[_to].size(), _cap);
G[_to].emplace_back(_from, (int)G[_from].size() - 1, 0);
}
T max_flow(const int source, const int sink){
s = source, t = sink;
int level = init();
while(level >= 0){
if(act_ver.empty(level)){
--level;
continue;
}
int u = act_ver.top(level);
act_ver.pop(level);
level = discharge(u);
if(checker >= V / 2){
level = global_relabel();
checker = 0;
}
}
// validate();
return excess[t];
}
};
constexpr ll INF = 1e18;
int u[1005], v[1005];
ll p[1005], q[1005], w[1005];
int main() {
cin.tie(0);
ios::sync_with_stdio(false);
int n, m;
ll d;
cin >> n >> m >> d;
for (int i = 0; i < m; i++) {
cin >> u[i] >> v[i] >> p[i] >> q[i] >> w[i];
u[i]--; v[i]--;
}
PushRelabel<ll> dn(n * m + 2);
for (int i = 1; i <= m; i++) dn.add_edge(0, i, INF);
for (int i = 0; i < m; i++) {
dn.add_edge(u[i] * m + i + 1, v[i] * m + i + 1, w[i]);
for (int j = 0; j < m; j++) {
if (v[j] == u[i] && q[j] + d <= p[i]) {
dn.add_edge(v[j] * m + j + 1, u[i] * m + i + 1, w[j]);
}
}
}
for (int i = 1; i <= m; i++) {
dn.add_edge((n - 1) * m + i, n * m + 1, INF);
}
cout << dn.max_flow(0, n * m + 1) << endl;
return 0;
}