zoukankan      html  css  js  c++  java
  • 2019 China Collegiate Programming Contest Qinhuangdao Onsite F. Forest Program(DFS计算图中所有环的长度)

    题目链接:https://codeforces.com/gym/102361/problem/F

    题意

    (n) 个点和 (m) 条边,每条边属于 (0)(1) 个环,问去掉一些边使得图变为森林的方案个数。

    题解

    找出所有环的长度 (c_i),每个环可以去掉 (1,2,dots,c_i) 条边,方案各为 (C_{c_i}^1,C_{c_i}^2, dots C_{c_i}^{c_i}),即 (2^{c_i} - 1)
    所有环的去边方案共有 (prod limits _{i = 1}^{c.size} 2^{c_i} - 1)
    余下的边为 (m - sum limits _{i=1}^{c.size} c_i),可以去掉 (0,1,2,dots,m - sum limits _{i=1}^{c.size} c_i) 条边,方案总数为 (2^{m - sum limits _{i=1}^{c.size} c_i})
    所以总的方案个数即为:({2^{m - sum limits _{i=1}^{c.size} c_i}} imes ({prod limits _{i = 1}^{c.size} 2^{c_i} - 1}))
    下面就是如何计算所有环的长度,利用 (dfs) 记录每个点的深度:

    • 如果下一个点深度小于当前点且访问过,那么二者深度之差加一即为所在环的长度。
    • 如果下一个点深度大于等于当前点,则该点之前已访问过且环的长度也已经计算过,可以跳过。

    Tips

    图可能不连通,所以需要对每个未访问过的点都进行 (dfs)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int MOD = 998244353;
    
    int binpow(int a, int b) {
        int res = 1;
        while (b) {
            if (b & 1) res = 1LL * res * a % MOD;
            a = 1LL * a * a % MOD;
            b >>= 1;
        }
        return res;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, m;
        cin >> n >> m;
        vector<vector<int>> G(n);
        for (int i = 0; i < m; i++) {
            int u, v;
            cin >> u >> v;
            --u, --v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        vector<int> dep(n), cycle;
        function<void(int, int)> dfs = [&](int u, int p) {
            if (dep[u] != 0) {
                if (dep[u] < dep[p])
                    cycle.push_back(dep[p] - dep[u] + 1);
            } else {
                dep[u] = (p == -1 ? 0 : dep[p]) + 1;
                for (auto v : G[u]) {
                    if (v != p) {
                        dfs(v, u);
                    }
                }
            }
        };
        for (int i = 0; i < n; i++) {
            if (dep[i] == 0) {
                dfs(i, -1);
            }
        }
        long long ans = binpow(2, m - accumulate(cycle.begin(), cycle.end(), 0));
        for (auto i : cycle) {
            ans *= binpow(2, i) - 1;
            ans %= MOD;
        }
        cout << ans << "
    ";
        return 0;
    }
    
  • 相关阅读:
    Tomcat与Spring中的事件机制详解
    Kafka消息系统基础知识索引
    配置SpringBoot-从日志系统配置说起
    支付宝手机网页支付和微信公众号支付接入
    centos下搭建YII环境
    为什么需要 Stream
    基于Django的Rest Framework框架的序列化组件
    基于Django的Rest Framework框架的RESTful规范研究
    web中状态码301和302的区别
    Django初见
  • 原文地址:https://www.cnblogs.com/Kanoon/p/13855321.html
Copyright © 2011-2022 走看看