Forest Program  CCPC 找环个数以及长度

题意:让我们把题目给出的图通过去边的方式,转化成森林,求出所有方案

思路:

   那么,森林由树构成,树为n个顶点,n-1条边

   有环的图不是树,所以在代码中,先把环的情况先计算出来,然后再看看剩下多少个顶点

   那么计算环,可以用dfs深搜而得,算出环中顶点个数,环的贡献权值为:2^n-1, (比如3条边,则就是0 0 1 ,0 1 0,0 1 1,到111这七种情况

   那么能0 0 0 吗?不可以,因为如果都不删除的话,就不是树

   然后剩下的所有顶点连接的边,都是可删可不删,直接2^k(k为边的个数)即可

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll mod=998244353;
 5 const int maxn=3e5+10;
 6 const int maxm=5e5+10;
 7 ll ans=1,sum;
 8 int vis[maxn];
 9 int pre[maxn];
10 struct node
11 {
12     int v,nxt;
13 }G[maxm*2];
14 int head[maxn];int num;
15 void add(int u,int v)
16 {
17     G[++num].v=v;G[num].nxt=head[u];head[u]=num;
18 }
19 ll qpow(ll a,ll b)
20 {
21     ll ans=1;
22     while(b){
23         if(b%2) ans=ans*a%mod;
24         b>>=1;
25         a=a*a%mod;
26     }
27     return ans;
28 }
29 void dfs(int u,int fa)
30 {
31     vis[u]=1;
32     for(int i=head[u];i;i=G[i].nxt){
33         int v=G[i].v;
34         if(v==fa) continue;
35         if(vis[v]==1){
36             int tmp=1;
37             int now=u;
38             while(now!=v){
39                 tmp++;
40                 now=pre[now];
41             }
42             sum+=tmp;
43             ans=ans*(qpow(2,tmp)-1)%mod;
44         }
45         else if(vis[v]==0){
46             pre[v]=u;
47             dfs(v,u);
48         }
49     }
50     vis[u]=2;
51 }
52 int main()
53 {
54     int n,m;
55     scanf("%d%d",&n,&m);
56     for(int i=1;i<=m;i++){
57         int u,v;
58         scanf("%d%d",&u,&v);
59         add(u,v);
60         add(v,u);
61     }
62     for(int i=1;i<=n;i++){
63         if(!vis[i]) dfs(i,0);
64     }
65     ans=ans*qpow(2,m-sum)%mod;
66     printf("%lld\n",ans);
67     return 0;
68 }

 

posted @ 2020-10-05 10:59  古比  阅读(215)  评论(0编辑  收藏  举报