1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| namespace Dinic { template<typename Tp> struct Dinic { struct RawEdge { uint32_t from, to; Tp cap; };
struct Edge { uint32_t to, rev; Tp cap;
bool operator>(const Edge &other) const { return cap > other.cap; } };
std::vector<RawEdge> m_rawEdges; std::vector<Edge> m_edges; std::vector<uint32_t> m_starts; uint32_t m_vertexNum;
Dinic(uint32_t _vertexNum, uint32_t __edgeNum);
void addEdge(uint32_t __a, uint32_t __b, Tp __cap) { m_rawEdges.push_back({__a, __b, __cap}); }
void prepare() { for (auto &[from, to, cap]: m_rawEdges) if (from != to) { m_starts[from + 1]++; m_starts[to + 1]++; } std::partial_sum(m_starts.begin(), m_starts.end(), m_starts.begin()); m_edges.resize(m_starts.back()); uint32_t cursor[m_vertexNum]; std::copy(m_starts.begin(), m_starts.begin() + m_vertexNum, cursor); for (auto &[from, to, cap]: m_rawEdges) if (from != to) { m_edges[cursor[from]] = Edge{to, cursor[to], cap}; m_edges[cursor[to]++] = Edge{from, cursor[from]++, 0}; } }
template<typename _Compare = std::greater<Edge>> void prepareSorted(_Compare __comp = _Compare()) { prepare(); for (uint32_t i = 0; i < m_vertexNum; i++) { uint32_t start = m_starts[i], end = m_starts[i + 1]; std::sort(m_edges.begin() + start, m_edges.begin() + end, __comp); for (uint32_t j = start; j < end; j++) m_edges[m_edges[j].rev].rev = j; } }
Tp calc(uint32_t _source, uint32_t _target, Tp _infiniteCap = std::numeric_limits<Tp>::max() / 2) { uint32_t queue[m_vertexNum], depth[m_vertexNum], it[m_vertexNum], end[m_vertexNum]; Tp res = 0; for (uint32_t i = 0; i < m_vertexNum; i++) end[i] = m_starts[i + 1]; auto dfs = [&](auto self, uint32_t i, Tp _cap) { if (i == _target || !_cap) return _cap; Tp flow = 0, f; for (uint32_t &cur = it[i]; cur != end[i]; cur++) if (auto &[to, rev, cap] = m_edges[cur]; depth[i] + 1 == depth[to] && (f = self(self, to, std::min(_cap, cap)))) if (flow += f, _cap -= f, cap -= f, m_edges[rev].cap += f; !_cap) break; return flow; }; while (true) { std::fill(depth, depth + m_vertexNum, -1); uint32_t head = 0, tail = 0; depth[_source] = 0; queue[tail++] = _source; while (head < tail) for (uint32_t from = queue[head++], cur = m_starts[from], end = m_starts[from + 1]; cur < end; cur++) if (auto &[to, rev, cap] = m_edges[cur]; cap && chmin(depth[to], depth[from] + 1)) queue[tail++] = to; if (!~depth[_target]) break; for (uint32_t i = 0; i < m_vertexNum; i++) it[i] = m_starts[i]; while (Tp flow = dfs(dfs, _source, _infiniteCap)) res += flow; } return res; } };
template<typename Tp> Dinic<Tp>::Dinic(uint32_t _vertexNum, uint32_t _edgeNum) : m_starts(_vertexNum + 1, 0), m_vertexNum(_vertexNum) { m_rawEdges.reserve(_edgeNum); } }
|