码迷,mamicode.com
首页 > 其他好文 > 详细

[CCPC2019秦皇岛] F. Forest Program

时间:2019-10-24 10:16:39      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:script   force   printf   森林   fine   sum   sign   乘法   class   

[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\n",ans);
}

[CCPC2019秦皇岛] F. Forest Program

标签:script   force   printf   森林   fine   sum   sign   乘法   class   

原文地址:https://www.cnblogs.com/mollnn/p/11730147.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!