diff --git a/lib/Graph/dinic.h b/lib/Graph/dinic.h new file mode 100644 index 0000000..f2ffa85 --- /dev/null +++ b/lib/Graph/dinic.h @@ -0,0 +1,79 @@ +#pragma once +#include "graph.h" +#include "template.h" + +template +class Dinic { + private: + int V; // 頂点数 + vector minCost; + vector iter; + AdjList graph; + const T INF = numeric_limits::max() / 10; + bool Bfs(int s, int t); + T Dfs(int idx, const int t, T flow); + + public: + explicit Dinic(int n); + void AddEdge(int from, int to, T cost); + T Run(int s, int t); +}; + +template +Dinic::Dinic(int n) : V(n), graph(n) {} + +template +void Dinic::AddEdge(int from, int to, T cost) { + graph[from].push_back(Edge(static_cast(graph[to].size()), to, cost)); + graph[to].push_back( + Edge(static_cast(graph[from].size() - 1), from, 0)); +} + +template +bool Dinic::Bfs(int s, int t) { + minCost.assign(graph.size(), -1); + queue que; + minCost[s] = 0; + que.push(s); + while (!que.empty()) { + int p = que.front(); + que.pop(); + for (auto &e : graph[p]) { + if (e.cost > 0 && minCost[e.to] < 0) { + minCost[e.to] = minCost[p] + 1; + que.push(e.to); + } + } + } + return (minCost[t] != -1); +} + +template +T Dinic::Dfs(int idx, const int t, T flow) { + if (idx == t) return flow; + for (int &i = iter[idx]; i < graph[idx].size(); ++i) { + Edge &e = graph[idx][i]; + if (e.cost > 0 && minCost[idx] < minCost[e.to]) { + T d = Dfs(e.to, t, min(flow, e.cost)); + if (d > 0) { + e.cost -= d; + graph[e.to][e.from].cost += d; + return d; + } + } + } + return 0; +} + +template +T Dinic::Run(int s, int t) { + T flow = 0; + while (Bfs(s, t)) { + iter.assign(graph.size(), 0); + T f = 0; + while ((f = Dfs(s, t, INF)) > 0) { + flow += f; + } + } + return flow; +}