题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6736
如果环的边长为k,那么环的删边方案数是2k-1。如果链的边长为k,那么链的删边方案数是2k。环的方案数乘以链的方案数就是总的方案数
#include<iostream> using namespace std; #define maxn 500005 #define mod 998244353 #define ll long long int cnt,n,m,head[maxn],deep[maxn],vis[maxn],tot; ll ans; struct edge{ int to,next; }e[maxn<<1]; void add(int u,int v) { e[++cnt].to=v; e[cnt].next=head[u]; head[u]=cnt; } ll poww(ll a,ll b) { ll ret=1; while(b) { if(b&1)ret=ret*a%mod; a=a*a%mod; b>>=1; } return ret; } void dfs(int u,int fa) { deep[u]=deep[fa]+1; int v; for(int i=head[u];i;i=e[i].next) { v=e[i].to; if(v!=fa) { if(!vis[v]) { vis[v]=1; dfs(v,u); } else if(deep[u]>deep[v]) { tot-=deep[u]-deep[v]+1; ans=ans*(poww(2,deep[u]-deep[v]+1)-1)%mod; } } } } int main() { int u,v; while(scanf("%d%d",&n,&m)!=EOF) { cnt=0; tot=m; for(int i=1;i<=n;i++) head[i]=deep[i]=vis[i]=0; for(int i=1;i<=m;i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } ans=1; for(int i=1;i<=n;i++) { if(!vis[i]) { vis[i]=1; dfs(i,i); } } ans=ans*poww(2,tot)%mod; printf("%lld\n",ans); } return 0; }