Problem Description
Z 国近年来一直在考虑遏制国土沙漠化的方案。在 Z 国广阔的疆域上,有着许多的沙漠。沙漠上干旱少雨,荒无人烟,仅有仙人掌能在这种魔鬼环境中生存。经过 Z 国地质探测局的调查,他们得到了沙漠的实地情况。Z 国的地质探测局是一个热爱 CCPC 的机构,他们喜欢使用图论的方式来描述看到的景色。在得到的数据中,沙漠中的每一个连通块都是一棵仙人掌;一个连通块是一棵仙人掌当且仅当连通块中不存在重边和自环,并且每一条边仅被至多一个简单环覆盖。
经过一番评估,Z 国决定通过删去沙漠中的一些边,最终将沙漠变为森林。这里我们定义森林满足:森林中每一个连通块都是一棵树,而树是边数等于点数减一的连通块。现在给定一个包含 n 个点的沙漠,请你求出 Z 国一共有多少种满足要求的沙漠改造方案。两种方案不同当且仅当方案中被删去的边集不同。由于答案可能很大,请将最终答案对 998244353 取模后输出。
Input
多组数据,每组数据第一行输入两个非负整数 n、m,分别表示沙漠中的点数和边数。沙漠中点的编号为 1, 2, ..., n。
对于每组数据的第 2 到第 m+1 行,每行输入两个正整数 u、v,表示沙漠中编号为 u 和编号为 v 的两个点之间有边相连。
1≤T≤3,1≤n≤3×105,m≤5×105,1≤u, v≤n 并且 u≠v。
Hint
样例解释
对于第一组样例,只需要至少删去一条边即可变为森林,故一共有 23−1=7 种方案。
Output
对于每一组数据,输出一行一个非负整数,表示答案对 998244353 取模后的值。
Sample Input
2 3 3 1 2 2 3 3 1 6 6 1 2 2 3 3 1 2 4 4 5 5 2
Sample Output
7 49
Source
642ccpcQHD
题解:关于有环是
无环的要计算在一起,计算
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mem(s) memset(s, 0, sizeof(s))
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const int maxn = 1e6+5;
const int mod = 998244353;
int vis[maxn],f[maxn];
ll res=1,res2=0;
int n,m,flag;
vector<int>G[maxn];
void init(){
memset(vis,0,sizeof(vis));
res=1,flag=0;
for(int i=1;i<=n;i++)G[i].clear();
}
ll mul(ll a,ll b){
return (a%mod)*(b%mod)%mod;
}
ll q_pow(ll a,ll b){
ll ans=1;
while(b){
if(b&1)ans=mul(ans,a);
a=mul(a,a);
b>>=1;
}
return ans;
}
void dfs(int fa,int u,int d){
//cout<<u<<endl;
vis[u]=1;f[u]=d;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v==fa)continue;
if(vis[v]){
if(d>f[v]){
flag=1;
res2+=d-f[v]+1;
res=mul(res,(q_pow(2,d-f[v]+1)-1+mod)%mod);
}
}else {
dfs(u,v,d+1);
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF){
init();
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
ll ans=1;
for(int i=1;i<=n;i++){
res=1;
if(!vis[i]){
dfs(-1,i,1);
ans=mul(res,ans);
}
}
printf("%lld\n",mul(ans,q_pow(2,m-res2)));
}
return 0;
}
/*
3 2
1 2
2 3
*/