#include #include #include #include #include #include "solution.cpp" static int failures = 0; #define CHECK(cond, name) do { if (cond) std::printf("ok %s\n", name); \ else { std::printf("FAIL %s (line %d)\n", name, __LINE__); ++failures; } } while (0) using E = std::tuple; int main() { { std::vector e = {{0, 1, 4}, {0, 2, 1}, {2, 1, 1}, {1, 3, 1}}; CHECK(shortest_path(4, e, 0, 3) == 3, "0->3 через 2: 1+1+1 = 3"); CHECK(shortest_path(4, e, 0, 0) == 0, "src == dst -> 0"); CHECK(shortest_path(4, e, 3, 0) == -1, "обратного пути нет -> -1"); CHECK(shortest_path(4, e, 0, 2) == 1, "прямой путь 0->2 = 1"); } { std::vector e = {{0, 1, 5}, {0, 2, 1}, {2, 1, 1}}; CHECK(shortest_path(3, e, 0, 1) == 2, "длинное ребро не должно побеждать короткий путь"); std::vector z = {{0, 1, 0}, {1, 2, 0}}; CHECK(shortest_path(3, z, 0, 2) == 0, "нулевые веса допустимы"); std::vector self = {{0, 0, 7}, {0, 1, 2}}; CHECK(shortest_path(2, self, 0, 1) == 2, "self-loop не ломает поиск"); std::vector par = {{0, 1, 3}, {0, 1, 7}}; CHECK(shortest_path(2, par, 0, 1) == 3, "параллельные рёбра: берём минимальное"); std::vector none; CHECK(shortest_path(2, none, 0, 1) == -1, "без рёбер -> -1"); } { // цепочка 0-1-2-...-(n-1) по 1000, плюс «ловушки»: обратные рёбра по 100000. // Ответ детерминирован: идти по цепочке дешевле, чем прыгать назад и снова вперёд. const int n = 100000; std::vector e; e.reserve(200000); for (int i = 0; i + 1 < n; ++i) e.emplace_back(i, i + 1, 1000); for (int i = 1; i < n; ++i) e.emplace_back(i, i - 1, 100000); e.emplace_back(0, 0, 99999999); auto t0 = std::chrono::steady_clock::now(); long long d = shortest_path(n, e, 0, n - 1); double sec = std::chrono::duration(std::chrono::steady_clock::now() - t0).count(); std::printf(" (100k вершин, 200k рёбер: dist=%lld, time=%.3fs)\n", d, sec); CHECK(d == (long long)(n - 1) * 1000, "цепочка: кратчайший путь по цепочке"); CHECK(sec < 2.0, "100k вершин за < 2 c"); } { // большие веса: сумма должна влезать в long long std::vector e; for (int i = 0; i + 1 < 2000; ++i) e.emplace_back(i, i + 1, 1000000); CHECK(shortest_path(2000, e, 0, 1999) == 1999LL * 1000000LL, "большие веса: 1999 * 1e6"); } std::printf(failures ? "\nFAILURES: %d\n" : "\nALL PASS\n", failures); return failures ? 1 : 0; }