[CCPC2019秦皇岛] F. Forest Program

Posted mollnn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CCPC2019秦皇岛] F. Forest Program相关的知识,希望对你有一定的参考价值。

[CCPC2019秦皇岛 F]

https://codeforces.com/gym/102361/problem/F

Description

给定一个仙人掌,删去一些边可以让它变成一个森林(一棵树也是森林),求方案数。 (n le 300000, m le 500000)

Solution

用 DFS 暴力找环,然后乘法原理算一下即可。注意非环边也会有贡献。

DFS 可以模仿 Tarjan 算法写。

Code
#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 300005;
const int modulo = 998244353;
vector <int> g[N];
int is[N],dis[N];
int n,m,t1,t2,t3,t4;
vector <int> sta,cir;

int qpow(int p,int q)
{
    int r=1;
    for(;q;p*=p,p%=modulo,q>>=1) if(q&1) r*=p,r%=modulo;
    return r;
}

void dfs(int p,int dep)
{
    is[p]=2;
    dis[p]=dep;
    sta.push_back(p);
    for(int i=0;i<g[p].size();i++)
    {
        int q=g[p][i];
        if(is[q]==2 && dep-dis[q]>1)
        {
            cir.push_back(dep+1-dis[q]);
        }
        else if(is[q]==0)
        {
            dfs(q,dep+1);
        }
    }
    sta.pop_back();
    is[p]=1;
}

signed main()
{
    scanf("%I64d%I64d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%I64d%I64d",&t1,&t2);
        g[t1].push_back(t2);
        g[t2].push_back(t1);
    }
    for(int i=1;i<=n;i++)
    {
        if(is[i]==0)
        {
            dfs(i,1);
        }
    }
    int sum=0,ans=1;
    for(int i=0;i<cir.size();i++)
    {
        ans*=(qpow(2ll,cir[i])-1ll);
        ans%=modulo;
        ans+=modulo;
        ans%=modulo;
        sum+=cir[i];
    }
    ans*=qpow(2ll,m-sum);
    ans%=modulo;
    printf("%I64d
",ans);
}

以上是关于[CCPC2019秦皇岛] F. Forest Program的主要内容,如果未能解决你的问题,请参考以下文章

Forest Program(2019ccpc秦皇岛F)

2019-ccpc秦皇岛现场赛

秦皇岛站2019CCPC A.Angel Beats

2019 CCPC秦皇岛 J 题 MUV LUV EXTRAKMP 求最小循环节

2019 CCPC秦皇岛 J 题 MUV LUV EXTRAKMP 求最小循环节

2019秦皇岛CCPC旅游小结