题目:http://acm.hdu.edu.cn/showproblem.php?pid=6736
思路:dfs+栈 判环
           设图中环的大小分别为 c1, c2, ..., ck,不属于任何一个环的 边数为 b,则答案为:
           ( 2 ^ c1 - 1 ) * ( 2 ^ c2 - 1 ) * ......* ( 2 ^ ck - 1 ) * 2 ^ b
           dfs判环时 各点入栈 若点已存在于栈中 则存在环 计算环大小即可 不必出栈
            跑一遍连通图即可计算出所有环

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e6+5;
const int mod=998244353;
vector<int>edge[maxn];
int vis[maxn],ins[maxn],s[maxn];
int top;
int n,m;
ll ans;
void init()
{
    ans=1;
    memset(vis,0,sizeof vis);
    memset(ins,0,sizeof ins);
    for(int i=1;i<=n;i++) edge[i].clear();
    top=0;
}
ll qPow(ll n,int a)
{
    ll res=1;
    while(a)
    {
        if(a&1) res=res*n%mod;
        n=n*n%mod;
        a>>=1;
    }
    return res;
}
void dfs(int u,int pre)
{
    s[++top]=u;
    ins[u]=1;
    vis[u]=1;
    for(auto x:edge[u])
    {
        if(!vis[x]) dfs(x,u);
        else if(ins[x]&&x!=pre)
        {
            int t=top;
            int sum=1;
            while(s[t]!=x)
            {
                t--;
                sum++;
            }
            m-=sum;
            ans=ans*(qPow(2,sum)-1+mod)%mod;
        }
    }
    ins[s[top]]=0;
    top--;
}
int main()
{
    int a,b;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            edge[a].push_back(b);
            edge[b].push_back(a);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])
                dfs(i,i);
        printf("%lld\n",ans*qPow(2,m)%mod);
    }
    return 0;
}
 
02-13 19:31