1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector>
using namespace std;
typedef unsigned long long ULL;
const int N = 1010, M = 510;
int n, m, T; int h[N], e[M], ne[M], idx; int dfn[N], low[N], timestamp; int stk[N], top; bool cut[N]; vector<int> dcc[N]; int id[N], dcc_cnt; int root;
void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx ++; }
void tarjan(int u) { dfn[u] = low[u] = ++ timestamp; stk[++ top] = u;
if (u == root && h[u] == -1) { dcc_cnt ++; dcc[dcc_cnt].push_back(u); return; }
int cnt = 0; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (!dfn[j]) { tarjan(j); low[u] = min(low[u], low[j]); if (dfn[u] <= low[j]) { cnt ++; if (u != root || cnt > 1) cut[u] = true; dcc_cnt ++; int y; do { y = stk[top --]; dcc[dcc_cnt].push_back(y); } while (y != j); dcc[dcc_cnt].push_back(u); } } else low[u] = min(low[u], dfn[j]); } }
int main() { T = 1; while (cin >> m, m) { for (int i = 1; i <= n; i ++ ) dcc[i].clear(); idx = timestamp = top = dcc_cnt = n = 0; memset(h, -1, sizeof h); memset(dfn, 0, sizeof dfn); memset(cut, 0, sizeof cut);
while (m --) { int a, b; cin >> a >> b; n = max(n, max(a, b)); add(a, b), add(b, a); }
for (root = 1; root <= n; root ++ ) if (!dfn[root]) tarjan(root);
int res = 0; ULL sum = 1; for (int i = 1; i <= dcc_cnt; i ++ ) { int cnt = 0; for (int j = 0; j < dcc[i].size(); j ++ ) if (cut[dcc[i][j]]) cnt ++; if (cnt == 0) { if (dcc[i].size() == 1) res ++; else res += 2, sum *= dcc[i].size() * (dcc[i].size() - 1) / 2; } else if (cnt == 1) res += 1, sum *= dcc[i].size() - 1; }
printf("Case %d: %d %llu\n", T, res, sum); T ++; }
return 0; }
|