#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=100005;
int n,m,Case;ll ans1,ans2;
int size,sum_cut,group,visit[N];
int root,timeclock,dfn[N],low[N],cut[N];
int tot,head[N],nxt[N],to[N];
inline void add(int a,int b){
nxt[++tot]=head[a];head[a]=tot;to[tot]=b;
}
inline void tarjan(int u){
dfn[u]=low[u]=++timeclock;
int child=0;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]){
++child;
if(u!=root||child>=2)cut[u]=1;
}
}
else low[u]=min(low[u],dfn[v]);
}
}
inline void dfs(int u){
visit[u]=group;++size;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(cut[v]&&visit[v]!=group){
++sum_cut;
visit[v]=group;
}
if(!visit[v])dfs(v);
}
}
int main(){
while(1){
int n=read();if(!n)return 0;
m=tot=timeclock=group=ans1=0;ans2=1;
memset(head,0,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(cut,0,sizeof(cut));
memset(visit,0,sizeof(visit));
printf("Case %d: ",++Case);
for(int i=1;i<=n;++i){
int a=read(),b=read();
add(a,b);add(b,a);
m=max(m,max(a,b));
}
for(int i=1;i<=m;++i)
if(!dfn[i])root=i,tarjan(i);
for(int i=1;i<=m;++i)
if(!visit[i]&&!cut[i]){
size=sum_cut=0;++group;
dfs(i);
if(sum_cut==0){
ans1+=2;
ans2=1ll*ans2*size*(size-1)/2;
}
if(sum_cut==1){
ans1+=1;
ans2=1ll*ans2*size;
}
}
printf("%lld %lld\n",ans1,ans2);
}
return 0;
}
[HNOI2012]矿场搭建/Mining Your Own Business
原文:https://www.cnblogs.com/PPXppx/p/11380973.html