1 module dkh.graph.maxflow; 2 3 import dkh.container.deque; 4 5 /// maxflowの情報 6 struct MaxFlowInfo(C) { 7 C flow; /// 流量 8 bool[] dual; /// 最小カット(S側:false, T側:true) 9 } 10 11 /** 12 MaxFlow(Dinic) 13 Params: 14 g = graph 15 s = source node 16 t = sink node 17 gap = maximum flow 18 */ 19 MaxFlowInfo!(C) maxFlow(C, C EPS, T)(T g, size_t s, size_t t, C gap = C.max) { 20 assert(s != t); 21 import std.conv : to; 22 int[] level = new int[g.length]; 23 int[] iter = new int[g.length]; 24 25 void bfs() { 26 level[] = -1; level[s] = 0; 27 auto que = Deque!int(); 28 que.insertBack(s.to!int); 29 while (!que.empty) { 30 int v = que.front; que.removeFront; 31 foreach (e; g[v]) { 32 if (e.cap <= EPS) continue; 33 if (level[e.to] < 0) { 34 level[e.to] = level[v] + 1; 35 que.insertBack(e.to); 36 } 37 } 38 } 39 } 40 41 C dfs(int v, C f) { 42 import std.algorithm : min; 43 if (v == t) return f; 44 C res = 0; 45 auto edgeList = g[v][iter[v]..$]; 46 foreach (ref e; edgeList) { 47 if (e.cap <= EPS) continue; 48 if (level[v] >= level[e.to]) continue; 49 C d = dfs(e.to, min(f, e.cap)); 50 e.cap -= d; 51 g[e.to][e.rev].cap += d; 52 res += d; 53 f -= d; 54 if (f == 0) break; 55 iter[v]++; 56 } 57 return res; 58 } 59 60 C flow = 0; 61 while (gap - flow > EPS) { 62 bfs(); 63 if (level[t] < 0) break; 64 iter[] = 0; 65 while (true) { 66 C f = dfs(s.to!int, gap - flow); 67 if (!f) break; 68 flow += f; 69 } 70 } 71 72 import std.algorithm : map; 73 import std.range : array; 74 auto mfInfo = MaxFlowInfo!C(); 75 mfInfo.flow = flow; 76 mfInfo.dual = level.map!"a == -1".array; 77 return mfInfo; 78 } 79 80 /// 81 unittest { 82 import std.algorithm : equal; 83 import std.conv : to; 84 struct Edge { 85 int to, cap, rev; 86 } 87 void addEdge(Edge[][] g, int from, int to, int cap) { 88 g[from] ~= Edge(to, cap, g[to].length.to!int); 89 g[to] ~= Edge(from, 0, g[from].length.to!int-1); 90 } 91 92 auto g = new Edge[][](4); 93 94 addEdge(g, 0, 1, 3); 95 addEdge(g, 0, 2, 3); 96 addEdge(g, 1, 3, 2); 97 addEdge(g, 2, 3, 4); 98 auto res = maxFlow!(int, 0)(g, 0, 3); 99 assert(res.flow == 5); 100 //MinCut : S={0, 1}, T={2, 3} 101 assert(equal(res.dual, [false, false, true, true])); 102 } 103 104 MaxFlowInfo!(C) maxFlowSlow(C, T)(T g, int s, int t, C gap = C.max) { 105 assert(s != t); 106 import std.algorithm : map; 107 import std.range : array; 108 import std.conv : to; 109 auto n = g.length; 110 111 bool[] used = new bool[n]; 112 bool dfs(int v) { 113 if (v == t) return true; 114 used[v] = true; 115 foreach (ref e; g[v]) { 116 if (used[e.to]) continue; 117 if (!e.cap) continue; 118 if (dfs(e.to)) { 119 e.cap -= 1; 120 g[e.to][e.rev].cap += 1; 121 return true; 122 } 123 } 124 return false; 125 } 126 127 C flow = 0; 128 while (flow < gap) { 129 used[] = false; 130 if (!dfs(s)) break; 131 flow++; 132 } 133 auto mfInfo = MaxFlowInfo!C(); 134 mfInfo.flow = flow; 135 mfInfo.dual = used.map!"!a".array; 136 return mfInfo; 137 } 138 139 unittest { 140 import std.algorithm, std.conv, std.stdio, std.range; 141 import std.random; 142 import std.typecons; 143 144 struct E { 145 int to, cap, rev; 146 } 147 void addEdge(E[][] g, int from, int to, int cap) { 148 g[from] ~= E(to, cap, g[to].length.to!int); 149 g[to] ~= E(from, 0, g[from].length.to!int-1); 150 } 151 152 void f(alias MF)() { 153 int n = uniform(2, 20); 154 int m = uniform(0, 200); 155 int s, t; 156 while (true) { 157 s = uniform(0, n); 158 t = uniform(0, n); 159 if (s != t) break; 160 } 161 auto g = new E[][n]; 162 E[][] elist = new E[][n]; 163 164 foreach (i; 0..m) { 165 int x, y; 166 while (true) { 167 x = uniform(0, n); 168 y = uniform(0, n); 169 if (x == y) continue; 170 break; 171 } 172 int c = uniform(0, 100); 173 addEdge(g, x, y, c); 174 elist[x] ~= E(y, c, -1); 175 } 176 177 auto res = MF(g, s, t); 178 assert(res.dual[s] == false); 179 assert(res.dual[t] == true); 180 int sm = 0; 181 foreach (i, v; elist) { 182 foreach (e; v) { 183 if (res.dual[i] == false && res.dual[e.to] == true) { 184 sm += e.cap; 185 } 186 } 187 } 188 assert(res.flow == sm); 189 } 190 191 import dkh.stopwatch; 192 auto ti = benchmark!( 193 f!(maxFlow!(int, 0, E[][])), 194 f!(maxFlowSlow!(int, E[][])), 195 )(1000); 196 writeln("MaxFlow Random1000: ", ti[].map!(a => a.toMsecs())); 197 } 198 199 unittest { 200 import std.algorithm, std.conv, std.stdio, std.range, std.math; 201 import std.random; 202 import std.typecons; 203 204 struct E { 205 int to; 206 double cap; 207 int rev; 208 } 209 void addEdge(E[][] g, int from, int to, double cap) { 210 g[from] ~= E(to, cap, g[to].length.to!int); 211 g[to] ~= E(from, 0.0, g[from].length.to!int-1); 212 } 213 immutable double EPS = 1e-9; 214 215 void f() { 216 int n = uniform(2, 20); 217 int m = uniform(0, 200); 218 int s = 0, t = 1; 219 auto g = new E[][n]; 220 E[][] elist = new E[][n]; 221 222 foreach (i; 1..m) { 223 int x, y; 224 while (true) { 225 x = uniform(0, n); 226 y = uniform(0, n); 227 if (x == y) continue; 228 break; 229 } 230 double c = uniform(0.0, 100.0); 231 addEdge(g, x, y, c); 232 elist[x] ~= E(y, c, -1); 233 } 234 235 auto res = maxFlow!(double, EPS)(g, 0, 1); 236 assert(res.dual[0] == false); 237 assert(res.dual[1] == true); 238 double sm = 0; 239 foreach (i, v; elist) { 240 foreach (e; v) { 241 if (res.dual[i] == false && res.dual[e.to] == true) { 242 sm += e.cap; 243 } 244 } 245 } 246 assert(abs(res.flow - sm) < EPS); 247 } 248 import dkh.stopwatch; 249 auto ti = benchmark!(f)(5000); 250 writeln("MaxFlow Double Random5000: ", ti[0].toMsecs()); 251 }