src/graph/euler_trail/lib.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "../ds/graph_c/lib.hpp" | ||
| 4 | |||
| 5 | namespace tifa_libs { | ||
| 6 | namespace euler_trail_impl_ { | ||
| 7 | template <bool cyc> | ||
| 8 | 48918 | CEXP auto run_(u32 n, u32 m, cT_(vvecptu) g, u32 s) NE { | |
| 9 | 48918 | std::optional ret(vecptu{}); | |
| 10 | 48918 | vec<vecptu::const_iterator> its(n); | |
| 11 |
2/2✓ Branch 3 taken 3680352 times.
✓ Branch 4 taken 48918 times.
|
3729270 | flt_ (u32, i, 0, n) its[i] = begin(g[i]); |
| 12 | 48918 | veci f(n); | |
| 13 | 48918 | if CEXP (!cyc) ++f[s]; | |
| 14 | 48918 | vecb vis(m); | |
| 15 | 97836 | vecptu stk = {{s, -1_u32}}; | |
| 16 |
2/2✓ Branch 1 taken 24520708 times.
✓ Branch 2 taken 48918 times.
|
24569626 | while (!stk.empty()) { |
| 17 | 24520708 | auto [i, p] = stk.back(); | |
| 18 | 24520708 | auto& it = its[i]; | |
| 19 |
2/2✓ Branch 3 taken 9793007 times.
✓ Branch 4 taken 14727701 times.
|
24520708 | if (it == end(g[i])) { |
| 20 | 9793007 | ret->emplace_back(i, p), stk.pop_back(); | |
| 21 | 9793007 | continue; | |
| 22 | } | ||
| 23 |
2/2✓ Branch 6 taken 9744089 times.
✓ Branch 7 taken 4983612 times.
|
14727701 | if (auto [j, e] = *(it++); !vis[e]) --f[i], ++f[j], stk.emplace_back(j, e), vis[e] = true; |
| 24 | } | ||
| 25 |
6/6✓ Branch 2 taken 45578 times.
✓ Branch 3 taken 3340 times.
✓ Branch 5 taken 14930 times.
✓ Branch 6 taken 30648 times.
✓ Branch 7 taken 18270 times.
✓ Branch 8 taken 30648 times.
|
2963994 | if (ret->size() != m + 1 || any_of(f, [](i32 i) { return i < 0; })) ret = std::nullopt; |
| 26 | 30648 | else reverse(ret.value()); | |
| 27 | 48918 | return ret; | |
| 28 | 48918 | } | |
| 29 | } // namespace euler_trail_impl_ | ||
| 30 | |||
| 31 | // @return vector of {v, eid} of Eulerian trail if found | ||
| 32 | // edges[eid[i]] = v[i-1] -> v[i], eid[0] = -1 | ||
| 33 | template <bool directed, bool cycle = false> | ||
| 34 | 48918 | CEXP auto euler_trail(u32 n, vecptu CR edges) NE { | |
| 35 | 97836 | vvecptu g(n); | |
| 36 | 48918 | vecu deg_in(0); | |
| 37 | 24496 | if CEXP (directed) deg_in.resize(n); | |
| 38 | 48918 | u32 e = 0; | |
| 39 |
4/4auto tifa_libs::euler_trail<false, false>(unsigned int, std::vector<std::pair<unsigned int, unsigned int>, std::allocator<std::pair<unsigned int, unsigned int> > > const&):
✓ Branch 6 taken 5000027 times.
✓ Branch 7 taken 24422 times.
auto tifa_libs::euler_trail<true, false>(unsigned int, std::vector<std::pair<unsigned int, unsigned int>, std::allocator<std::pair<unsigned int, unsigned int> > > const&):
✓ Branch 6 taken 5000031 times.
✓ Branch 7 taken 24496 times.
|
10048976 | for (auto [u, v] : edges) { |
| 40 | 10000058 | g[u].emplace_back(v, e); | |
| 41 | 5000031 | if CEXP (directed) ++deg_in[v]; | |
| 42 | 5000027 | else g[v].emplace_back(u, e); | |
| 43 | 10000058 | ++e; | |
| 44 | } | ||
| 45 | 48918 | u32 s = 0; | |
| 46 |
4/4auto tifa_libs::euler_trail<false, false>(unsigned int, std::vector<std::pair<unsigned int, unsigned int>, std::allocator<std::pair<unsigned int, unsigned int> > > const&):
✓ Branch 1 taken 1815765 times.
✓ Branch 2 taken 24422 times.
auto tifa_libs::euler_trail<true, false>(unsigned int, std::vector<std::pair<unsigned int, unsigned int>, std::allocator<std::pair<unsigned int, unsigned int> > > const&):
✓ Branch 1 taken 1815669 times.
✓ Branch 2 taken 24496 times.
|
3680352 | flt_ (u32, i, 1, (u32)g.size()) |
| 47 |
4/4auto tifa_libs::euler_trail<false, false>(unsigned int, std::vector<std::pair<unsigned int, unsigned int>, std::allocator<std::pair<unsigned int, unsigned int> > > const&):
✓ Branch 2 taken 1311186 times.
✓ Branch 3 taken 504579 times.
auto tifa_libs::euler_trail<true, false>(unsigned int, std::vector<std::pair<unsigned int, unsigned int>, std::allocator<std::pair<unsigned int, unsigned int> > > const&):
✓ Branch 2 taken 1251212 times.
✓ Branch 3 taken 564457 times.
|
3631434 | if (!g[i].empty()) s = i; |
| 48 |
4/4auto tifa_libs::euler_trail<false, false>(unsigned int, std::vector<std::pair<unsigned int, unsigned int>, std::allocator<std::pair<unsigned int, unsigned int> > > const&):
✓ Branch 1 taken 1840187 times.
✓ Branch 2 taken 24422 times.
auto tifa_libs::euler_trail<true, false>(unsigned int, std::vector<std::pair<unsigned int, unsigned int>, std::allocator<std::pair<unsigned int, unsigned int> > > const&):
✓ Branch 1 taken 1840165 times.
✓ Branch 2 taken 24496 times.
|
3729270 | flt_ (u32, i, 0, (u32)g.size()) |
| 49 | if CEXP (directed) { | ||
| 50 |
2/2✓ Branch 3 taken 165227 times.
✓ Branch 4 taken 1674938 times.
|
1840165 | if (deg_in[i] < g[i].size()) s = i; |
| 51 |
2/2✓ Branch 2 taken 221254 times.
✓ Branch 3 taken 1618933 times.
|
1840187 | } else if (g[i].size() & 1) s = i; |
| 52 | 48918 | return euler_trail_impl_::run_<cycle>(n, (u32)edges.size(), g, s); | |
| 53 | 48918 | } | |
| 54 | template <graph_c G> | ||
| 55 | 137 | CEXP bool is_eulerian(G CR g) NE { | |
| 56 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 137 times.
|
137 | retif_((!g.esize()) [[unlikely]], 1); |
| 57 | 137 | cu32 n = g.vsize(); | |
| 58 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 137 times.
|
137 | assert(n == g.din.size()); |
| 59 |
2/2✓ Branch 0 taken 28486 times.
✓ Branch 1 taken 109 times.
|
28595 | flt_ (u32, i, 0, n) |
| 60 |
2/2✓ Branch 2 taken 28 times.
✓ Branch 3 taken 28458 times.
|
28486 | if (g.din[i] != g.dout[i]) return false; |
| 61 | 109 | u32 loopv = 0, loope = 0, start = 0; | |
| 62 |
2/2✓ Branch 0 taken 28458 times.
✓ Branch 1 taken 109 times.
|
28567 | flt_ (u32, u, 0, n) { |
| 63 |
2/2✓ Branch 2 taken 8108 times.
✓ Branch 3 taken 20350 times.
|
28458 | if (g[u].empty()) continue; |
| 64 | 20350 | bool f = true; | |
| 65 |
2/2✓ Branch 6 taken 19910724 times.
✓ Branch 7 taken 20350 times.
|
19931074 | for (start = u; auto v : g[u]) |
| 66 |
2/2✓ Branch 1 taken 1332906 times.
✓ Branch 2 taken 18577818 times.
|
19910724 | if (u == (u32)v) ++loope; |
| 67 | 18577818 | else f = false; | |
| 68 | 20350 | loopv += f; | |
| 69 | } | ||
| 70 |
8/8✓ Branch 0 taken 103 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 96 times.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 7 times.
✓ Branch 8 taken 102 times.
|
109 | if (loopv > 1 || (loopv == 1 && loope != g.esize())) return false; |
| 71 | 102 | vecb vis(n); | |
| 72 | 34786 | auto f = [&](auto&& f, u32 x) NE -> void { | |
| 73 |
2/2✓ Branch 6 taken 18710709 times.
✓ Branch 7 taken 17342 times.
|
18728051 | for (auto v : g[x]) |
| 74 |
2/2✓ Branch 3 taken 17240 times.
✓ Branch 4 taken 18693469 times.
|
18710709 | if (!vis[(u32)v]) vis[(u32)v] = true, f(f, (u32)v); |
| 75 | }; | ||
| 76 | 102 | vis[start] = true, f(f, start); | |
| 77 |
2/2✓ Branch 0 taken 25448 times.
✓ Branch 1 taken 100 times.
|
25548 | flt_ (u32, i, 0, n) |
| 78 |
6/6✓ Branch 2 taken 8110 times.
✓ Branch 3 taken 17338 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 8108 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 25446 times.
|
25448 | if (!vis[i] && g.din[i]) return false; |
| 79 | 100 | return true; | |
| 80 | 102 | } | |
| 81 | |||
| 82 | } // namespace tifa_libs | ||
| 83 |