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 }