Submission #393937

#TimeUsernameProblemLanguageResultExecution timeMemory
393937KoDDuathlon (APIO18_duathlon)C++17
100 / 100
141 ms30492 KiB
#include <bits/stdc++.h>

using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;
using i128 = __int128_t;
using u128 = __uint128_t;
using isize = std::ptrdiff_t;
using usize = std::size_t;

class rep {
    struct Iter {
        usize itr;
        constexpr Iter(const usize pos) noexcept : itr(pos) {}
        constexpr void operator++() noexcept { ++itr; }
        constexpr bool operator!=(const Iter& other) const noexcept {
            return itr != other.itr;
        }
        constexpr usize operator*() const noexcept { return itr; }
    };
    const Iter first, last;

  public:
    explicit constexpr rep(const usize first, const usize last) noexcept
        : first(first), last(std::max(first, last)) {}
    constexpr Iter begin() const noexcept { return first; }
    constexpr Iter end() const noexcept { return last; }
};

template <class F> struct RecLambda : private F {
    template <class G>
    explicit constexpr RecLambda(G&& g) : F(std::forward<G>(g)) {}
    template <class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
        return F::operator()(*this, std::forward<Args>(args)...);
    }
};

template <class G> explicit RecLambda(G&&) -> RecLambda<std::decay_t<G>>;

template <class T> bool setmin(T& lhs, const T& rhs) {
    if (lhs > rhs) {
        lhs = rhs;
        return true;
    }
    return false;
}

template <class T> using Vec = std::vector<T>;

void APIO18A_main() {
    usize N, M;
    std::cin >> N >> M;
    Vec<Vec<usize>> graph(N);
    while (M--) {
        usize a, b;
        std::cin >> a >> b;
        a -= 1;
        b -= 1;
        graph[a].push_back(b);
        graph[b].push_back(a);
    }
    Vec<Vec<usize>> bctree(N);
    const auto add_node = [&] {
        const auto ret = bctree.size();
        bctree.push_back({});
        return ret;
    };
    Vec<usize> depth(N), ord(N), low(N);
    usize time = 0;
    std::stack<usize> store;
    const auto dfs = RecLambda(
        [&](auto&& dfs, const usize u, const usize p, const usize d) -> void {
            depth[u] = d;
            ord[u] = low[u] = time;
            time += 1;
            store.push(u);
            for (const auto v : graph[u])
                if (v != p) {
                    if (depth[v] == 0) {
                        dfs(v, u, d + 1);
                        if (ord[u] <= low[v]) {
                            const auto node = add_node();
                            bctree[u].push_back(node);
                            while (bctree[node].empty() or
                                   bctree[node].back() != v) {
                                bctree[node].push_back(store.top());
                                store.pop();
                            }
                        }
                        setmin(low[u], low[v]);
                    } else {
                        setmin(low[u], ord[v]);
                    }
                }
        });
    Vec<usize> roots;
    for (const auto root : rep(0, N)) {
        if (depth[root] == 0) {
            dfs(root, root, 1);
            roots.push_back(root);
        }
    }
    Vec<usize> subtree(bctree.size());
    u64 ans = 0;
    usize whole = 0;
    const auto calc = RecLambda([&](auto&& dfs, const usize u) -> void {
        subtree[u] = (u < N);
        for (const auto v : bctree[u]) {
            dfs(v);
            subtree[u] += subtree[v];
            if (u >= N) {
                ans -= (u64)bctree[u].size() * subtree[v] * (subtree[v] - 1);
            }
        }
    });
    const auto flush = RecLambda([&](auto&& dfs, const usize u) -> void {
        if (u >= N) {
            ans -= (u64)bctree[u].size() * (whole - subtree[u]) *
                   (whole - subtree[u] - 1);
        }
        for (const auto v : bctree[u]) {
            dfs(v);
        }
    });
    for (const auto root : roots) {
        calc(root);
        whole = subtree[root];
        ans += (u64)whole * (whole - 1) * (whole - 2);
        flush(root);
    }
    std::cout << ans << '\n';
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
    APIO18A_main();
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...