2019 CCPC 重现赛 1006 基环树
- 2019 年 10 月 10 日
- 筆記
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_41603898/article/details/101621445
设图中环的大小分别为 c1, c2, …, ck,不属于任何一个环的
边数为 b,则答案为:2^b* (2^c1 – 1)*…*(2^ck – 1)
#include<bits/stdc++.h> using namespace std; const int maxn = 3e5 + 10; const int mod = 998244353; typedef long long ll; vector<int> g[maxn]; int t,n,m,tot = 0,sz = 0,cnt; int dfn[maxn],f[maxn]; vector<int> pot[maxn]; void dfs(int u,int fa) { dfn[u] = ++sz; bool t = false; for(int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if(v == fa) continue; if(!dfn[v]) { f[v] = u; dfs(v,u); } else if(dfn[v] < dfn[u]) continue; else if(dfn[v] > dfn[u]) { ++cnt; for(int p = v; p != u; p = f[p]) pot[cnt].push_back(p); pot[cnt].push_back(u); continue; } } } ll fpow(ll a,ll b) { ll r = 1; while(b) { if(b & 1) r = r * a % mod; a = a * a % mod; b >>= 1; } return r; } int main() { scanf("%d%d",&n,&m); for(int i = 1; i <= m; i++) { int u,v; scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } ll ans = 1; for(int i = 1; i <= n; i++) { if(!dfn[i]) { dfs(i,0); } } for(int i = 1; i <= cnt; i++) { ans = ans * (fpow(2,pot[i].size()) - 1) % mod; m -= pot[i].size(); } ans = ans * fpow(2,m) % mod; printf("%lldn",ans); return 0; }