|
1 | 1 | using FluentAssertions;
|
| 2 | +using MersenneTwister; |
2 | 3 | using Xunit;
|
3 | 4 |
|
4 | 5 | namespace AtCoder
|
@@ -78,5 +79,87 @@ public void Invalid()
|
78 | 79 | g.Invoking(g => g.AddEdge(0, 0, -1, 0)).Should().ThrowDebugAssertIfDebug();
|
79 | 80 | g.Invoking(g => g.AddEdge(0, 0, 0, -1)).Should().ThrowDebugAssertIfDebug();
|
80 | 81 | }
|
| 82 | + |
| 83 | + [Fact] |
| 84 | + public void Stress() |
| 85 | + { |
| 86 | + var mt = MTRandom.Create(); |
| 87 | + for (int phase = 0; phase < 1000; phase++) |
| 88 | + { |
| 89 | + int n = mt.Next(2, 21); |
| 90 | + int m = mt.Next(1, 101); |
| 91 | + var (s, t) = mt.NextPair(0, n); |
| 92 | + if (mt.NextBool()) (s, t) = (t, s); |
| 93 | + |
| 94 | + var gMf = new MFGraphInt(n); |
| 95 | + var g = new McfGraphInt(n); |
| 96 | + for (int i = 0; i < m; i++) |
| 97 | + { |
| 98 | + int u = mt.Next(0, n); |
| 99 | + int v = mt.Next(0, n); |
| 100 | + int cap = mt.Next(0, 11); |
| 101 | + int costIn = mt.Next(0, 10001); |
| 102 | + g.AddEdge(u, v, cap, costIn); |
| 103 | + gMf.AddEdge(u, v, cap); |
| 104 | + } |
| 105 | + var (flow, cost) = g.Flow(s, t); |
| 106 | + gMf.Flow(s, t).Should().Be(flow); |
| 107 | + |
| 108 | + int cost2 = 0; |
| 109 | + var vCap = new int[n]; |
| 110 | + foreach (var e in g.Edges()) |
| 111 | + { |
| 112 | + vCap[e.From] -= e.Flow; |
| 113 | + vCap[e.To] += e.Flow; |
| 114 | + cost2 += e.Flow * e.Cost; |
| 115 | + } |
| 116 | + cost.Should().Be(cost2); |
| 117 | + |
| 118 | + for (int i = 0; i < n; i++) |
| 119 | + { |
| 120 | + if (i == s) |
| 121 | + { |
| 122 | + (-flow).Should().Be(vCap[i]); |
| 123 | + } |
| 124 | + else if (i == t) |
| 125 | + { |
| 126 | + flow.Should().Be(vCap[i]); |
| 127 | + } |
| 128 | + else |
| 129 | + { |
| 130 | + vCap[i].Should().Be(0); |
| 131 | + } |
| 132 | + } |
| 133 | + |
| 134 | + // check: there is no negative-cycle |
| 135 | + var dist = new int[n]; |
| 136 | + while (true) |
| 137 | + { |
| 138 | + bool update = false; |
| 139 | + foreach (var e in g.Edges()) |
| 140 | + { |
| 141 | + if (e.Flow < e.Cap) |
| 142 | + { |
| 143 | + int ndist = dist[e.From] + e.Cost; |
| 144 | + if (ndist < dist[e.To]) |
| 145 | + { |
| 146 | + update = true; |
| 147 | + dist[e.To] = ndist; |
| 148 | + } |
| 149 | + } |
| 150 | + if (e.Flow != 0) |
| 151 | + { |
| 152 | + int ndist = dist[e.To] - e.Cost; |
| 153 | + if (ndist < dist[e.From]) |
| 154 | + { |
| 155 | + update = true; |
| 156 | + dist[e.From] = ndist; |
| 157 | + } |
| 158 | + } |
| 159 | + } |
| 160 | + if (!update) break; |
| 161 | + } |
| 162 | + } |
| 163 | + } |
81 | 164 | }
|
82 | 165 | }
|
0 commit comments