关键在于怎样找到各个环及其边数。
- dfs搜
- 双连通分量
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef pair<int,int> piir; 4 typedef long long ll; 5 const int maxn = 3e5+5; 6 const int maxm = 5e5+5; 7 const int INF = 0x3f3f3f3f; 8 const int mod = 998244353; 9 10 int n,m,vis[maxn],dfn[maxn]; 11 ll ans,sum; 12 13 struct edge{ 14 int v,next; 15 }e[maxm*2]; 16 int head[maxn],tot; 17 void init(){ 18 memset(head,-1,sizeof(head));tot=0; 19 ans=1; 20 sum=0; 21 memset(vis,0,sizeof(vis)); 22 memset(dfn,0,sizeof(dfn)); 23 } 24 void add(int u,int v){ 25 e[tot].v=v; 26 e[tot].next=head[u]; 27 head[u]=tot++; 28 } 29 30 ll qpow(ll base,ll n) { 31 ll ans = 1; 32 while (n) { 33 if (n & 1) ans = (ans % mod) * (base % mod) % mod; 34 base = (base % mod) * (base % mod) % mod; 35 n >>= 1; 36 } 37 return ans % mod; 38 } 39 void dfs(int u,int fa,int stp){ 40 //printf("u:%d fa:%d stp%d\n",u,fa,stp); 41 42 vis[u]=1;dfn[u]=stp; 43 for(int i=head[u];i!=-1;i=e[i].next){ 44 int v=e[i].v; 45 if(v==fa || vis[v]==2) continue; 46 if(vis[v]==1){// find circle 47 sum += (stp-dfn[v]+1); 48 //printf("u%d v%d stp%d dfnv%d\n",u,v,stp,dfn[v]); 49 ans = (ans*(qpow(2,stp-dfn[v]+1)-1))%mod; 50 //printf("ans:%d\n",ans); 51 continue; 52 } 53 dfs(v,u,stp+1); 54 } 55 vis[u]=2; 56 } 57 int main(){ 58 //freopen("in.txt","r",stdin); 59 while(scanf("%d%d",&n,&m)!=EOF){ 60 init(); 61 for(int u,v,i=1;i<=m;i++){ 62 scanf("%d%d",&u,&v); 63 add(u,v),add(v,u); 64 } 65 for(int i=1;i<=n;i++){ 66 if(vis[i]==0) { 67 dfs(i,-1,0); 68 } 69 } 70 ans = (ans*qpow(2,m-sum))%mod; 71 printf("%lld\n",ans); 72 } 73 return 0; 74 }
原文地址:https://www.cnblogs.com/ordinarv/p/11778325.html
时间: 2024-11-09 23:38:16