题意:给了一幅无向图,不存在重边,存在简单环,不存在自环。 现在让你删除任意条数的边,让这个图变成一片森林,即每个联通块都是一棵树,即不存在环。
思路:首先对于每个环上的所有边,我们至少要删除一条。 所以每个环的贡献就是2 ^(cnt)- 1 ,其中num是环上边的总数。 对于原图中不是环上的边,那么可删可不删,每条边的贡献就是2。 对于不是环上的边的数量,我们可以算出环上的边有cnt条,num=m-cnt就是非环上的边。 贡献就是2 ^ num 最后通过dfs求环即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+5; const ll mod=998244353; vector<int> e[N]; int vis[N]; ll ans; int n,m,num; ll qpow(ll a,ll b){ ll ans=1; while(b){ if(b&1) ans=ans*a%mod; b>>=1; a=a*a%mod; } return ans; } void dfs(int now,int x,int f){ vis[x]=now; for(auto it:e[x]){ if(it==f) continue; if(!vis[it]) { dfs(now+1,it,x); } else if(vis[it]<vis[x]){ num+=vis[x]-vis[it]+1; ans=ans*(qpow(2,vis[x]-vis[it]+1)-1)%mod; ans+=mod; ans%=mod; } } } int main(){ while(~scanf("%d%d",&n,&m)){ for(int i=1;i<=n;i++) e[i].clear(),vis[i]=0; ans=1; num=0; for(int i=1;i<=m;i++){ int x,y;scanf("%d%d",&x,&y); e[x].push_back(y); e[y].push_back(x); } dfs(1,1,-1); printf("%lld\n",ans*qpow(2,m-num)%mod); } return 0; }