仅作代码分享
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int MAXN = 50007;
struct edge {
int u, v;
edge(int tu, int tv):u(tu), v(tv) {}
};
vector<int> G[MAXN], bcc[MAXN];
int pt[MAXN], low[MAXN];
int bccno[MAXN];
int bccn, dt;
bool iscut[MAXN];
stack<edge> sg;
int dfs(int u, int fa) {
pt[u] = low[u] = ++dt;
int i, sz = G[u].size(), child = 0;
for(i = 0; i < sz; i++) {
int v = G[u][i];
edge tmp(u,v);
if( !pt[v] ) {
child ++;
sg.push(tmp);
low[u] = min(low[u], dfs(v, u));
if(low[v] >= pt[u]) {
iscut[u] = true;
bccn ++; bcc[bccn].clear();
while( !sg.empty() ) {
tmp = sg.top(); sg.pop();
if(bccno[tmp.u] != bccn) {
bccno[tmp.u] = bccn;
bcc[bccn].push_back(tmp.u);
}
if(bccno[tmp.v] != bccn) {
bccno[tmp.v] = bccn;
bcc[bccn].push_back(tmp.v);
}
if(tmp.u == u && tmp.v == v) break;
}
}
}
else if(pt[v] < pt[u] && v != fa) {
sg.push(tmp);
low[u] = min(low[u], pt[v]);
}
}
if(fa < 1 && child < 2) iscut[u] = false;
return low[u];
}
void getbcc(int n) {
while( !sg.empty() ) sg.pop();
bccn = dt = 0;
memset(pt, 0, sizeof(pt));
memset(bccno, 0, sizeof(bccno));
memset(iscut, 0, sizeof(iscut));
for(int i = 1; i <= n; i++)
if( !pt[i] ) dfs(i, 0);
}
int main() {
int n, id = 0;
while(~scanf("%d", &n), n) {
int i, j, u, v, N = 1;
for(i = 1; i <= n+1; i++) G[i].clear();
for(i = 1; i <= n; i++) {
scanf("%d%d", &u, &v);
N = max(N, u);
N = max(N, v);
G[u].push_back(v);
G[v].push_back(u);
}
getbcc(N);
ll ans0 = 0, ans1 = 1;
if(bccn < 2) {
ans0 = 2;
ans1 = (ll)N * (N - 1) / 2;
}
else {
for(i = 1; i <= bccn; i++) {
int ncut = 0, sz = bcc[i].size();
for(j = 0; j < sz; j++)
if(iscut[bcc[i][j]]) ncut++;
if(ncut > 1) continue;
ans0 ++;
ans1 *= sz - 1;
}
}
printf("Case %d: %lld %lld\n", ++id, ans0, ans1);
}
return 0;
}