无向图的双连通分量
#include<cstdio> #include<stack> #include<vector> #include<map> #include<algorithm> #include<cstring> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; typedef long long LL; const int maxn = 50010; struct Edge { int u, v; Edge(int u, int v):u(u), v(v) {} }; int pre[maxn], low[maxn], bccno[maxn], iscut[maxn], bcc_cnt, dfs_clock; vector<int> g[maxn], bcc[maxn]; stack<Edge> S; int dfs(int u, int fa) { int lowu = pre[u] = ++dfs_clock; int child = 0; for(int i = 0; i < g[u].size(); i++) { int v = g[u][i]; Edge e = Edge(u, v); if(!pre[v]) { S.push(e); child++; int lowv = dfs(v, u); lowu = min(lowu, lowv); if(lowv >= pre[u]) { iscut[u] = 1; bcc_cnt++; bcc[bcc_cnt].clear(); for(;;) { Edge x = S.top(); S.pop(); if(bccno[x.u] != bcc_cnt) { bccno[x.u] = bcc_cnt; bcc[bcc_cnt].push_back(x.u); } if(bccno[x.v] != bcc_cnt) { bccno[x.v] = bcc_cnt; bcc[bcc_cnt].push_back(x.v); } if(x.u == u && x.v == v) break; } } } else if(pre[v] < pre[u] && v!= fa) { S.push(e); lowu = min(lowu, pre[v]); } } if(child == 1 && fa < 0) iscut[u] = 0; return low[u] = lowu; } void find_bcc(int n) { memset(iscut, 0, sizeof(iscut)); memset(pre, 0, sizeof(pre)); memset(bccno, 0, sizeof(bccno)); dfs_clock = bcc_cnt = 0; for(int i = 0; i < n; i++) if(!pre[i]) dfs(i, -1); } int kase; void solve(int n) { find_bcc(n); LL ans1 = 0, ans2 = 1; for(int i = 1; i <= bcc_cnt; i++) { int cut_cnt = 0; for(int j = 0; j < bcc[i].size(); j++) if(iscut[bcc[i][j]]) cut_cnt++; if(cut_cnt == 1) ans1++, ans2 *= (LL)(bcc[i].size() - cut_cnt); } if(bcc_cnt == 1) { ans1 = 2, ans2 = (LL)(n-1)*n/2; } printf("Case %d: %I64d %I64d\n", kase, ans1, ans2); } int main(void) { int m; while(scanf("%d", &m), m) { kase++; for(int i = 0; i < maxn; i++) g[i].clear(); int mxn = 0; while(m--) { int u, v; scanf("%d%d", &u, &v); mxn = max(mxn, max(u, v)); u--, v--; g[u].push_back(v), g[v].push_back(u); } solve(mxn); } return 0; }
时间: 2024-10-24 13:59:23