|
| 1 | +#include <atcoder/maxflow> |
1 | 2 | #include <atcoder/mincostflow>
|
| 3 | + |
2 | 4 | #include <numeric>
|
3 | 5 | #include <tuple>
|
4 | 6 | #include <vector>
|
| 7 | +#include "../utils/random.hpp" |
5 | 8 |
|
6 | 9 | #include <gtest/gtest.h>
|
7 | 10 |
|
@@ -66,7 +69,7 @@ TEST(MincostflowTest, Assign) {
|
66 | 69 |
|
67 | 70 | TEST(MincostflowTest, OutOfRange) {
|
68 | 71 | mcf_graph<int, int> g(10);
|
69 |
| - |
| 72 | + |
70 | 73 | EXPECT_DEATH(g.slope(-1, 3), ".*");
|
71 | 74 | EXPECT_DEATH(g.slope(3, 3), ".*");
|
72 | 75 | }
|
@@ -95,3 +98,69 @@ TEST(MincostflowTest, Invalid) {
|
95 | 98 | EXPECT_DEATH(g.add_edge(0, 0, -1, 0), ".*");
|
96 | 99 | EXPECT_DEATH(g.add_edge(0, 0, 0, -1), ".*");
|
97 | 100 | }
|
| 101 | + |
| 102 | +TEST(MincostflowTest, Stress) { |
| 103 | + for (int phase = 0; phase < 1000; phase++) { |
| 104 | + int n = randint(2, 20); |
| 105 | + int m = randint(1, 100); |
| 106 | + int s, t; |
| 107 | + std::tie(s, t) = randpair(0, n - 1); |
| 108 | + if (randbool()) std::swap(s, t); |
| 109 | + |
| 110 | + mf_graph<int> g_mf(n); |
| 111 | + mcf_graph<int, int> g(n); |
| 112 | + for (int i = 0; i < m; i++) { |
| 113 | + int u = randint(0, n - 1); |
| 114 | + int v = randint(0, n - 1); |
| 115 | + int cap = randint(0, 10); |
| 116 | + int cost = randint(0, 10000); |
| 117 | + g.add_edge(u, v, cap, cost); |
| 118 | + g_mf.add_edge(u, v, cap); |
| 119 | + } |
| 120 | + int flow, cost; |
| 121 | + std::tie(flow, cost) = g.flow(s, t); |
| 122 | + ASSERT_EQ(g_mf.flow(s, t), flow); |
| 123 | + |
| 124 | + int cost2 = 0; |
| 125 | + std::vector<int> v_cap(n); |
| 126 | + for (auto e : g.edges()) { |
| 127 | + v_cap[e.from] -= e.flow; |
| 128 | + v_cap[e.to] += e.flow; |
| 129 | + cost2 += e.flow * e.cost; |
| 130 | + } |
| 131 | + ASSERT_EQ(cost, cost2); |
| 132 | + |
| 133 | + for (int i = 0; i < n; i++) { |
| 134 | + if (i == s) { |
| 135 | + ASSERT_EQ(-flow, v_cap[i]); |
| 136 | + } else if (i == t) { |
| 137 | + ASSERT_EQ(flow, v_cap[i]); |
| 138 | + } else { |
| 139 | + ASSERT_EQ(0, v_cap[i]); |
| 140 | + } |
| 141 | + } |
| 142 | + |
| 143 | + // check: there is no negative-cycle |
| 144 | + std::vector<int> dist(n); |
| 145 | + while (true) { |
| 146 | + bool update = false; |
| 147 | + for (auto e : g.edges()) { |
| 148 | + if (e.flow < e.cap) { |
| 149 | + int ndist = dist[e.from] + e.cost; |
| 150 | + if (ndist < dist[e.to]) { |
| 151 | + update = true; |
| 152 | + dist[e.to] = ndist; |
| 153 | + } |
| 154 | + } |
| 155 | + if (e.flow) { |
| 156 | + int ndist = dist[e.to] - e.cost; |
| 157 | + if (ndist < dist[e.from]) { |
| 158 | + update = true; |
| 159 | + dist[e.from] = ndist; |
| 160 | + } |
| 161 | + } |
| 162 | + } |
| 163 | + if (!update) break; |
| 164 | + } |
| 165 | + } |
| 166 | +} |
0 commit comments