hdu 6736 Forest Program ###K
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6736
题意:给定一个无向连通图 要删除一些边使得其变成一些树 问有多少种方案
思路:每个环除了一条边不删 其他都可以 假设是n元环 就是2^n-1 种 不是环的边可删可不删 所有是 2^n
那么剩下的就是考虑如何找出图中所有的环是几元环了,m-边就是剩下的不是环的边
考虑用dfs 和vis记录时间 来做 每个点最多跑2遍
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int maxn =3e5+10; 6 const int mod=998244353; 7 int n,m; 8 vector<int>E[maxn]; 9 vector<int>cnt; 10 int vis[maxn]; 11 int pre[maxn]; 12 13 14 ll power(ll base,ll n) 15 { 16 ll r=1; 17 while(n) 18 { 19 if(n%2) r=r*base%mod; 20 base=base*base%mod; 21 n/=2; 22 } 23 return r; 24 } 25 int tot; 26 27 void dfs(int u) 28 { 29 vis[u]=++tot; 30 for(auto &v:E[u]) 31 { 32 if(v==pre[u]) 33 continue; 34 if(vis[v]==0) 35 dfs(v),pre[v]=u; 36 else if(vis[v]>vis[u]) 37 { 38 int t=v; 39 int sum=1; 40 while(t!=u) 41 { 42 sum++; 43 t=pre[t]; 44 } 45 cnt.pb(sum); 46 } 47 } 48 49 } 50 51 52 53 54 int main() 55 { 56 ios::sync_with_stdio(false); 57 cin.tie(0); 58 while(cin>>n>>m) 59 { 60 for(int i=1;i<=n;i++) 61 E[i].clear(),vis[i]=0,pre[i]=0; 62 cnt.clear(); 63 tot=0; 64 int sum=m; 65 while(m--) 66 { 67 int u,v; 68 cin>>u>>v; 69 E[u].pb(v); 70 E[v].pb(u); 71 } 72 dfs(1); 73 ll ans=1; 74 for(auto &v:cnt) 75 { 76 ll temp=power(2,v)-1; 77 ans*=temp; 78 ans%=mod; 79 sum-=v; 80 } 81 ans*=power(2,sum); 82 ans%=mod; 83 cout<<ans<<'\n'; 84 85 } 86 87 88 89 }
也可以直接套点双模板 每个大于等于3的点双连通分量就是一个几元环
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int mod=998244353; 6 const int maxn=3e5+10; 7 8 ll power(ll base,ll n) 9 { 10 ll r=1; 11 while(n) 12 { 13 if(n%2) r=r*base%mod; 14 base=base*base%mod; 15 n/=2; 16 } 17 return r; 18 } 19 20 21 struct edge 22 { 23 int u,v; 24 }; 25 vector<edge>G[maxn]; 26 vector<int>vdccs[maxn]; 27 int dfn[maxn],low[maxn],tot,vdcc[maxn],bridge,iscnt[maxn],vdcnt; 28 void init(int n) 29 { 30 bridge=0,vdcnt=0,tot=0; 31 for(int i=1;i<=n;i++) 32 { 33 G[i].clear(),dfn[i]=0,vdcc[i]=0,iscnt[i]=0; 34 } 35 } 36 void add(int u,int v) 37 { 38 G[u].pb({u,v}); 39 G[v].pb({v,u}); 40 } 41 stack<edge>s; 42 43 void dfs(int u,int fa) 44 { 45 dfn[u]=low[u]=++tot; 46 int child=0; 47 for(auto &e:G[u]) 48 { 49 if(!dfn[e.v]) 50 { 51 s.push(e); 52 child++; 53 dfs(e.v,u); 54 low[u]=min(low[u],low[e.v]); 55 if(dfn[u]<=low[e.v]) 56 { 57 if(dfn[u]<low[e.v]) bridge++; 58 iscnt[u]=1; 59 vdccs[++vdcnt].clear(); 60 edge t; 61 do 62 { 63 t=s.top(); 64 s.pop(); 65 if(vdcc[t.u]!=vdcnt) 66 { 67 vdccs[vdcnt].pb(t.u); 68 vdcc[t.u]=vdcnt; 69 } 70 if(vdcc[t.v]!=vdcnt) 71 { 72 vdccs[vdcnt].pb(t.v); 73 vdcc[t.v]=vdcnt; 74 } 75 } 76 while(t.u!=e.u||t.v!=e.v); 77 } 78 } 79 else if(e.v!=fa&&dfn[u]>dfn[e.v]) 80 { 81 low[u]=min(low[u],dfn[e.v]); 82 s.push(e); 83 } 84 85 } 86 if(fa==u&&child==1) iscnt[u]=0; 87 } 88 89 90 int main() 91 { 92 ios::sync_with_stdio(0); 93 cin.tie(0); 94 int n,m; 95 while(cin>>n>>m) 96 { 97 init(n); 98 for(int i=0;i<m;i++) 99 { 100 int x,y; 101 cin>>x>>y; 102 add(x,y); 103 } 104 for(int i=1;i<=n;i++) 105 { 106 if(!dfn[i]) 107 dfs(i,i); 108 } 109 ll ans=1; 110 int sum=0; 111 for(int i=1;i<=vdcnt;i++) 112 { 113 int len=vdccs[i].size(); 114 if(len>=3) 115 { 116 sum+=len; 117 ans*=power(2,len)-1; 118 ans=(ans+mod)%mod; 119 } 120 } 121 int temp=m-sum; 122 ans=ans*power(2,temp); 123 ans%=mod; 124 cout<<ans<<'\n'; 125 } 126 127 128 129 130 131 }

浙公网安备 33010602011771号