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 }
View Code

 

也可以直接套点双模板  每个大于等于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 }
View Code

 

posted @ 2020-09-26 08:52  canwinfor  阅读(207)  评论(0)    收藏  举报