|
1 | 1 | #include <bits/stdc++.h>
|
2 |
| -// 首先调用MCMF::init()设置点的个数,源点和汇点 |
3 |
| -// 调用MCMF::addedge()加边 |
4 |
| -// 调用MCMF::solve()计算答案,答案存在MinCost和MaxFlow里面 |
5 |
| -namespace MCMF { |
6 |
| - typedef int flow_t; |
7 |
| - typedef int cost_t; |
8 |
| - const int MAXN = 200, MAXM = 100000; |
| 2 | + |
| 3 | +template<typename flow_t, typename cost_t> |
| 4 | +struct MCMF { |
| 5 | + static const int N = 200, M = 100000; |
9 | 6 | const flow_t inf = 1e9;
|
10 |
| - struct Edge { |
11 |
| - int from, to, nx; |
| 7 | + struct node { |
| 8 | + int from, to, nxt; |
12 | 9 | flow_t cap, flow;
|
13 | 10 | cost_t cost;
|
14 |
| - Edge() {} |
15 |
| - Edge(int _from, int _to, int _nx, flow_t _cap, cost_t _cost): |
16 |
| - from(_from), to(_to), nx(_nx), cap(_cap), flow(0), cost(_cost) {} |
17 |
| - } E[MAXM]; |
18 |
| - cost_t dis[MAXN]; |
19 |
| - int G[MAXN], pre[MAXN], vis[MAXN]; |
20 |
| - int sz, N; //S源点, T汇点 |
| 11 | + node() {} |
| 12 | + node(int from, int to, int nxt, flow_t cap, cost_t cost): |
| 13 | + from(from), to(to), nxt(nxt), cap(cap), flow(0), cost(cost) {} |
| 14 | + } E[M]; |
| 15 | + cost_t dis[N]; |
| 16 | + int G[N], pre[N], vis[N], n, m; |
21 | 17 | void init(int n) {
|
22 |
| - memset(G, -1, sizeof(G[0]) * n); |
23 |
| - sz = 0; N = n; |
| 18 | + this->n = n; |
| 19 | + this->m = 0; |
| 20 | + std::fill(G, G + n, -1); |
24 | 21 | }
|
25 |
| - void addedge(int u, int v, flow_t f, cost_t c) {//u -> v |
26 |
| - E[sz] = Edge(u, v, G[u], f, +c); G[u] = sz++; |
27 |
| - E[sz] = Edge(v, u, G[v], 0, -c); G[v] = sz++; |
| 22 | + void link(int u, int v, flow_t f, cost_t c) { |
| 23 | + E[m] = node(u, v, G[u], f, +c); G[u] = m++; |
| 24 | + E[m] = node(v, u, G[v], 0, -c); G[v] = m++; |
28 | 25 | }
|
29 | 26 | bool extand(int S, int T) {
|
30 |
| - std::queue<int> Q; |
31 |
| - memset(vis, 0, sizeof(vis[0]) * N); |
32 |
| - memset(pre, -1, sizeof(pre[0]) * N); |
33 |
| - for (int i = 0; i < N; ++i) dis[i] = inf; |
34 |
| - Q.push(S); vis[S] = 1; dis[S] = 0; |
35 |
| - while (!Q.empty()) { |
36 |
| - int u = Q.front(); |
37 |
| - Q.pop(); vis[u]=0; |
38 |
| - for (int it = G[u]; ~it; it = E[it].nx) { |
| 27 | + std::fill(vis, vis + n, 0); |
| 28 | + std::fill(dis, dis + n, inf); |
| 29 | + std::queue<int> queue; |
| 30 | + dis[S] = 0; |
| 31 | + queue.push(S); |
| 32 | + for (; !queue.empty(); queue.pop()) { |
| 33 | + int u = queue.front(); |
| 34 | + vis[u] = false; |
| 35 | + for (int it = G[u]; ~it; it = E[it].nxt) { |
39 | 36 | int v = E[it].to;
|
40 | 37 | if (E[it].cap > E[it].flow && dis[v] > dis[u] + E[it].cost) {
|
41 |
| - dis[v] = dis[u] + E[it].cost, pre[v] = it; |
42 |
| - if (!vis[v]) Q.push(v), vis[v] = true; |
| 38 | + dis[v] = dis[u] + E[it].cost; |
| 39 | + pre[v] = it; |
| 40 | + if (!vis[v]) queue.push(v); |
| 41 | + vis[v] = true; |
43 | 42 | }
|
44 | 43 | }
|
45 | 44 | }
|
46 | 45 | return dis[T] < inf; // 改成dis[T] <= 0 求可行流
|
47 | 46 | }
|
48 |
| - std::pair<flow_t, cost_t> solve(int S, int T) { |
49 |
| - flow_t MaxFlow = 0; |
50 |
| - cost_t MinCost = 0; |
| 47 | + std::pair<flow_t, cost_t> run(int S, int T) { |
| 48 | + flow_t max_flow = 0; |
| 49 | + cost_t min_cost = 0; |
51 | 50 | while (extand(S, T)) {
|
52 |
| - flow_t aug = inf; |
53 |
| - for (int it = pre[T]; ~it; it = pre[E[it].from]) { |
54 |
| - aug = std::min(aug, E[it].cap - E[it].flow); |
| 51 | + flow_t delta = inf; |
| 52 | + for (int u = T; u != S; u = E[pre[u]].from) { |
| 53 | + delta = std::min(delta, E[pre[u]].cap - E[pre[u]].flow); |
55 | 54 | }
|
56 |
| - MinCost += aug * dis[T], MaxFlow += aug; |
57 |
| - for (int it = pre[T]; ~it; it = pre[E[it].from]) { |
58 |
| - E[it].flow += aug, E[it ^ 1].flow -= aug; |
| 55 | + min_cost += delta * dis[T]; |
| 56 | + max_flow += delta; |
| 57 | + for (int u = T; u != S; u = E[pre[u]].from) { |
| 58 | + E[pre[u]].flow += delta; |
| 59 | + E[pre[u] ^ 1].flow -= delta; |
59 | 60 | }
|
60 | 61 | }
|
61 |
| - return std::make_pair(MaxFlow, MinCost); |
| 62 | + return {max_flow, min_cost}; |
62 | 63 | }
|
63 |
| -} |
| 64 | +}; |
64 | 65 |
|
65 |
| -namespace ZKW { |
66 |
| - const int MAXN = 50000 + 10, MAXM = 300000, inf = 1e9; |
67 |
| - typedef int VAL; |
68 |
| - struct Edge { |
69 |
| - int v,f; |
70 |
| - VAL c; |
71 |
| - int nx; |
72 |
| - Edge() {} |
73 |
| - Edge(int v,int f,VAL c,int nx):v(v),f(f),c(c),nx(nx) {} |
74 |
| - } E[MAXM]; |
75 |
| - int G[MAXN], Q[MAXN]; |
76 |
| - VAL dis[MAXN],mincost; |
77 |
| - bool vis[MAXN],mark[MAXN]; |
78 |
| - int N,S,T,sz; |
79 |
| - void init(int _n, int _s, int _t) { |
80 |
| - N = _n; S = _s; T = _t; sz = 0; |
81 |
| - memset(G, -1, sizeof(G[0]) * N); |
| 66 | +template<typename flow_t, typename cost_t> |
| 67 | +struct MCMF_ZKW { |
| 68 | + static const int N = 200, M = 3000, inf = 1e9; |
| 69 | + struct node { |
| 70 | + int to, nxt; |
| 71 | + flow_t cap, flow; |
| 72 | + cost_t cost; |
| 73 | + node() {} |
| 74 | + node(int to, int nxt, flow_t cap, cost_t cost): |
| 75 | + to(to), nxt(nxt), cap(cap), flow(0), cost(cost) {} |
| 76 | + } E[M]; |
| 77 | + int G[N], n, m; |
| 78 | + cost_t min_cost, len; |
| 79 | + flow_t max_flow; |
| 80 | + bool done[N]; |
| 81 | + void init(int n) { |
| 82 | + this->n = n; |
| 83 | + this->m = 0; |
| 84 | + std::fill(G, G + n, -1); |
82 | 85 | }
|
83 |
| - void link(int u, int v, int f, VAL c) { |
84 |
| - E[sz]=Edge(v,f,+c,G[u]); G[u]=sz++; |
85 |
| - E[sz]=Edge(u,0,-c,G[v]); G[v]=sz++; |
| 86 | + void link(int u, int v, flow_t f, cost_t c) { |
| 87 | + E[m] = node(v, G[u], f, +c); G[u] = m++; |
| 88 | + E[m] = node(u, G[v], 0, -c); G[v] = m++; |
86 | 89 | }
|
87 |
| - bool spfa() { |
88 |
| - for (int i=0;i<N;++i) dis[i]=inf,vis[i]=0; |
89 |
| - dis[T]=0; Q[0]=T; vis[T]=1; |
90 |
| - for (int h=0,t=1;h!=t; ) { |
91 |
| - int u=Q[h++],v; vis[u]=false; |
92 |
| - if (h==MAXN) h=0; |
93 |
| - for (int it=G[u];~it;it=E[it].nx) { |
94 |
| - if (dis[u]-E[it].c<dis[v=E[it].v]&&E[it^1].f) { |
95 |
| - dis[v]=dis[u]-E[it].c; |
96 |
| - if (!vis[v]) { |
97 |
| - vis[v]=true; Q[t++]=v; |
98 |
| - if (t==MAXN) t=0; |
99 |
| - } |
100 |
| - } |
| 90 | + flow_t aug(int now, int T, flow_t max_cap) { |
| 91 | + if (now == T) { |
| 92 | + max_flow += max_cap; |
| 93 | + min_cost += max_cap * len; |
| 94 | + return max_cap; |
| 95 | + } |
| 96 | + done[now] = true; |
| 97 | + flow_t upp = max_cap; |
| 98 | + for (int it = G[now]; ~it && upp; it = E[it].nxt) { |
| 99 | + if (E[it].cap > E[it].flow && !E[it].cost && !done[E[it].to]) { |
| 100 | + flow_t delta = aug(E[it].to, T, std::min(upp, E[it].cap - E[it].flow)); |
| 101 | + E[it].flow += delta; |
| 102 | + E[it ^ 1].flow -= delta; |
| 103 | + upp -= delta; |
101 | 104 | }
|
102 | 105 | }
|
103 |
| - return dis[S]!=inf; |
| 106 | + return max_cap - upp; |
104 | 107 | }
|
105 |
| - int dfs(int u, int low) { |
106 |
| - mark[u]=true; if (u==T) return low; |
107 |
| - int ret=0,tmp=0; |
108 |
| - for (int it=G[u],v;~it&&ret<low;it=E[it].nx) { |
109 |
| - if (E[it].f&&!mark[v=E[it].v]&&dis[u]-E[it].c==dis[v]) { |
110 |
| - tmp=dfs(v,std::min(E[it].f,low-ret)); |
111 |
| - E[it].f-=tmp; E[it^1].f+=tmp; |
112 |
| - mincost+=E[it].c*tmp; ret+=tmp; |
| 108 | + bool label(int S, int T) {//不能用于负费用 |
| 109 | + cost_t delta = inf; |
| 110 | + for (int u = 0; u < n; ++u) if (done[u]) { |
| 111 | + for (int it = G[u]; ~it; it = E[it].nxt) { |
| 112 | + if (E[it].cap > E[it].flow && !done[E[it].to]) { |
| 113 | + delta = std::min(delta, E[it].cost); |
| 114 | + } |
| 115 | + } |
| 116 | + } |
| 117 | + if (delta == inf) return false; |
| 118 | + for (int u = 0; u < n; ++u) if (done[u]) { |
| 119 | + for (int it = G[u]; ~it; it = E[it].nxt) { |
| 120 | + E[it].cost -= delta; |
| 121 | + E[it ^ 1].cost += delta; |
113 | 122 | }
|
114 | 123 | }
|
115 |
| - return ret; |
| 124 | + len += delta; |
| 125 | + return true; |
116 | 126 | }
|
117 |
| - VAL solve() { |
118 |
| - int maxflow = 0; mincost = 0; |
119 |
| - while (spfa()) { |
120 |
| - mark[T] = true; |
121 |
| - while (mark[T]) { |
122 |
| - memset(mark, 0, sizeof(mark[0]) * N); |
123 |
| - maxflow += dfs(S, inf); |
| 127 | + cost_t dis[N]; |
| 128 | + bool label_primal_dual(int S, int T) { |
| 129 | + for (int i = 0; i < n; ++i) dis[i] = inf; |
| 130 | + std::fill(done, done + n, 0); |
| 131 | + dis[T] = 0; |
| 132 | + std::queue<int> queue; |
| 133 | + queue.push(T); |
| 134 | + for (; !queue.empty(); queue.pop()) { |
| 135 | + int u = queue.front(); |
| 136 | + done[u] = false; |
| 137 | + for (int it = G[u]; ~it; it = E[it].nxt) { |
| 138 | + int v = E[it].to; |
| 139 | + cost_t cost = dis[u] - E[it].cost; |
| 140 | + if (E[it ^ 1].cap > E[it ^ 1].flow && cost < dis[v]) { |
| 141 | + dis[v] = cost; |
| 142 | + if (!done[v]) queue.push(v); |
| 143 | + done[v] = true; |
| 144 | + } |
| 145 | + } |
| 146 | + } |
| 147 | + for (int u = 0; u < n; ++u) { |
| 148 | + for (int it = G[u]; ~it; it = E[it].nxt) { |
| 149 | + E[it].cost += dis[E[it].to] - dis[u]; |
124 | 150 | }
|
125 | 151 | }
|
126 |
| - return mincost; |
| 152 | + len += dis[S]; |
| 153 | + return dis[S] < inf; |
| 154 | + } |
| 155 | + std::pair<flow_t, cost_t> run_primal_dual(int S, int T) { |
| 156 | + max_flow = min_cost = len = 0; |
| 157 | + while (label_primal_dual(S, T)) { |
| 158 | + do { |
| 159 | + std::fill(done, done + n, 0); |
| 160 | + } while (aug(S, T, inf)); |
| 161 | + } |
| 162 | + return {max_flow, min_cost}; |
| 163 | + } |
| 164 | + std::pair<flow_t, cost_t> run(int S, int T) { |
| 165 | + max_flow = min_cost = len = 0; |
| 166 | + do { |
| 167 | + do { |
| 168 | + std::fill(done, done + n, 0); |
| 169 | + } while (aug(S, T, inf)); |
| 170 | + } while (label_primal_dual(S, T)); |
| 171 | + return {max_flow, min_cost}; |
127 | 172 | }
|
128 |
| -} |
| 173 | +}; |
0 commit comments