代码
#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const ll maxn = 100010;
struct Edge
{
ll u,v;
Edge(ll u,ll v):u(u),v(v){}
};
stack<Edge>S;
ll pre[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt;
vector<ll>G[maxn],bcc[maxn];
ll dfs(ll u,ll fa)
{
ll lowu=pre[u]=++dfs_clock;
ll child=0;
for(unsigned int i=0;i<G[u].size();i++)
{
ll v=G[u][i];
Edge e=(Edge){u,v};
if(!pre[v])
{
child++;
S.push(e);
ll lowv=dfs(v,u);
lowu=min(lowu,lowv);
if(lowv>=pre[u])
{
iscut[u]=1;
bcc_cnt++;
bcc[bcc_cnt].clear();
for(;;)
{
Edge e=S.top();S.pop();
if(bccno[e.u]!=bcc_cnt){bccno[e.u]=bcc_cnt;bcc[bcc_cnt].push_back(e.u);}
if(bccno[e.v]!=bcc_cnt){bccno[e.v]=bcc_cnt;bcc[bcc_cnt].push_back(e.v);}
if(e.u==u&&e.v==v) break;
}
}
}
else if(pre[v]<pre[u]&&fa!=v)
{
S.push(e);
lowu=min(lowu,pre[v]);
}
}
if(fa<0&&child==1) iscut[u]=0;
return lowu;
}
void find_bcc(ll n)
{
dfs_clock=bcc_cnt=0;
for(ll i=1;i<=n;i++) if(!pre[i])
dfs(i,-1);
}
ll kase;
ll N;
map<ll,ll>id;
ll ID;
int main()
{
while(scanf("%lld",&N)==1&&N)
{
ll u,v;
id.clear();
ID=0;
rep(i,1,N)
{
ll j=i<<1;
ll jj=j-1;
G[j].clear();
G[jj].clear();
bcc[j].clear();
bcc[jj].clear();
pre[j]=iscut[j]=bccno[j]=0;
pre[jj]=iscut[jj]=bccno[jj]=0;
}
rep(i,1,N)
{
scanf("%lld %lld",&u,&v);
if(!id[u]) id[u]=++ID;
u=id[u];
if(!id[v]) id[v]=++ID;
v=id[v];
G[u].push_back(v);
G[v].push_back(u);
}
find_bcc(ID);
printf("Case %lld: ",++kase);
if(bcc_cnt==1) printf("2 %lld\n",1ll*ID*(ID-1)/2);
else
{
ll cnt=0,num=1;
rep(i,1,bcc_cnt)
{
ll cut=0;
for(unsigned int j=0;j<bcc[i].size();j++)
if(iscut[bcc[i][j]])
{
cut++;
if(cut>1) break;
}
if(cut==1)
{
cnt++;
num*=bcc[i].size()-1;
}
}
printf("%lld %lld\n",cnt,num);
}
}
return 0;
}