#include #include #include #include #include #include template struct mccf_graph{ int n; // input edges struct edge_with_function{ int from, to; std::function F; // must be discrete convex Flow cap, flow; }; // edges on the residual graph struct edge{ int to, rev, id; bool available; Cost cost; bool is_rev; // for debug void print_edge(){ std::cerr << "to: " << to << " cost: " << cost << "\n";} }; std::vector> g; std::vector E; std::vector dual; mccf_graph() {} mccf_graph(int n) : n(n), g(n){ dual.resize(n, 0); } int add_edge(int from, int to, std::function F, Flow cap, Flow flow){ assert(0 <= from and from < n); assert(0 <= to and to < n); // assert(cap > 0); int m = int(E.size()); E.push_back(edge_with_function{from, to, F, cap, flow}); return m; } Cost calc_objective(){ Cost obj = 0; for(auto &e: E){ obj += e.F(e.flow); } return obj; } /* for debug void print_g(){ for(int i=0;i::max()); } void solve_SSP(int s, int t, Flow flow_limit){ assert(0 <= s and s < n); assert(0 <= t and t < n); assert(s != t); // construct a residual graph int m = E.size(); for(int i=0;i dist(n, 0); std::vector pv(n), pe(n); std::vector vis(n); auto dual_ref_Dijkstra = [&]()->bool{ fill(dist.begin(), dist.end(), std::numeric_limits::max()); fill(pv.begin(), pv.end(), -1); fill(pe.begin(), pe.end(), -1); fill(vis.begin(), vis.end(), false); struct Q{ Cost key; int to; bool operator<(Q r) const {return key > r.key;}; }; std::priority_queue que; dist[s] = 0; que.push(Q{0, s}); while(!que.empty()){ int v = que.top().to; que.pop(); if(vis[v]) continue; vis[v] = true; if(v == t) break; for(int i=0;i<(int)g[v].size();i++){ auto &e = g[v][i]; if(vis[e.to] or !e.available) continue; Cost cost = e.cost - dual[e.to] + dual[v]; if(dist[e.to] - dist[v] > cost){ dist[e.to] = dist[v] + cost; pv[e.to] = v; pe[e.to] = i; que.push(Q{dist[e.to], e.to}); } } } if(!vis[t]){ return false; } // assert(vis[t]); for(int v=0;vbool{ fill(dist.begin(), dist.end(), std::numeric_limits::max()); fill(pv.begin(), pv.end(), -1); fill(pe.begin(), pe.end(), -1); fill(vis.begin(), vis.end(), false); dist[s] = 0; vis[s] = true; for(int itr=0;itr dist[v] + e.cost){ dist[e.to] = dist[v] + e.cost; pv[e.to] = v; pe[e.to] = i; vis[e.to] = true; } } } } // check feasibility if(!vis[t]){ return false; } // detect negative cycle for(int v=0;v= dist[e.to]); } } for(int v=0;v> N >> M; std::vector A(N), B(N); for(int i=0;i> A[i]; for(int i=0;i> B[i]; std::vector> T(N, std::vector(N, 0)); for(int i=0;i> T[i][j]; } } // assert int A_sum = 0, B_sum = 0; for(int i=0;i= 0); A_sum += A[i]; } for(int i=0;i= 0); B_sum += B[i]; } assert(A_sum == M); assert(B_sum == M); // graph construction mccf_graph G(2*N+2); int s = 2*N; int t = s+1; int INF_cap = 1e9; for(int i=0;i> res(N, std::vector(N, 0)); for(auto &e: G.E){ if(e.from != s and e.to!= t){ res[e.from][e.to-N] = e.flow; } } // for(int i=0;i