2019 CCPC秦皇岛 F Forest Program

关键在于怎样找到各个环及其边数。

  1. dfs搜
  2. 双连通分量
 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 }

猜你喜欢

转载自www.cnblogs.com/ordinarv/p/11778325.html