#include<bits/stdc++.h>
using namespace std;
const int maxm=505;
long long n,s,t,cnt,tim,tot,cans,res1,res2=1,id,C;
long long has[maxm*maxm],head[maxm*maxm],to[maxm],nex[maxm],dfn[maxm*maxm],low[maxm*maxm],st[maxm*maxm],is_cut[maxm*maxm];
map<long long,long long>appear;
struct ans{
vector<long long>id;
long long cnt_cut=0;
}a[maxm*maxm];
long long getnum(long long x){
if(appear[x]) return appear[x];
appear[x]=++id;
return id;
}
void add(long long u,long long v){
to[++cnt]=v;
nex[cnt]=head[u];
head[u]=cnt;
}
void Tarjan(long long u){
dfn[u]=low[u]=++tim;
st[++tot]=u;
for(long long i=head[u];i;i=nex[i]){
if(!dfn[to[i]]){
Tarjan(to[i]);
low[u]=min(low[i],low[to[i]]);
if(dfn[u]<=low[to[i]]){
cans++;
is_cut[u]=1;
while(st[tot]!=u)
has[st[tot]]=1,a[cans].id.push_back(st[tot--]);
a[cans].id.push_back(u);
}
}
else low[u]=min(low[u],dfn[to[i]]);
}
}
void init(){
for(long long i=1;i<=cans;i++) a[i].id.clear();
appear.clear();
n=id=s=t=cnt=tim=tot=cans=res1=0;
res2=1;
memset(has,0,sizeof(has));
memset(head,0,sizeof(head));
memset(to,0,sizeof(to));
memset(nex,0,sizeof(nex));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(st,0,sizeof(st));
memset(is_cut,0,sizeof(is_cut));
}
int main(){
while(1){
cin>>n;
if(!n) return 0;
for(long long i=1;i<=n;i++){
cin>>s>>t;
s=getnum(s);
t=getnum(t);
add(s,t);
add(t,s);
}
for(long long i=1;i<=n;i++)
if(!dfn[i])
Tarjan(i);
for(long long i=1;i<=cans;i++)
for(long long j=0;j<a[cans].id.size();j++)
if(is_cut[j])
a[i].cnt_cut++;
for(long long i=1;i<=n;i++)
if(!has[i])
res1++;
for(long long i=1;i<=cans;i++)
if(a[i].cnt_cut>=2);
else if(a[i].cnt_cut==1) res1++,res2*=(a[i].id.size()-1);
else res1+=2,res2*=(a[i].id.size()-1)*a[i].id.size()/2;
cout<<"Case "<<++C<<": "<<res1<<' '<<res2<<'\n';
init();
}
}