final的题,求割点的模版
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#define N 200100
using namespace std;
typedef long long ll;
int head[N],cnt;
int depth,dfn[N],low[N];
bool cut[N],vis[N];
vector<int>vec;
struct Edge{
int v,next;
}edge[N];
ll num,cutnum;
int cas,gen;
void addedge(int u,int v){
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].v=u;
edge[cnt].next=head[v];
head[v]=cnt++;
}
void init(){
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn));
dfn[0]=0; ///////
memset(cut,0,sizeof(cut));
memset(vis,0,sizeof(vis));
cnt=depth=0;
}
void tarjan(int u,int fa){
dfn[u]=low[u]=dfn[fa]+1; ////// 注意这里要写dfn[fa]+1,而非++depth
int child=0,i;
for(i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa)continue;
if(dfn[v]==0){
tarjan(v,u);
low[u]=min(low[u],low[v]);
child++;
}
else
low[u]=min(low[u],dfn[v]);
}
if(u==gen){
if(child>1) cut[u]=1;
else cut[u]=0;
}
else{
for(i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(dfn[v]==dfn[u]+1) ///////
if(low[v]>=dfn[u]){
cut[u]=1;
break;
}
}
}
}
void find(int u){
if(cut[u]){
vec.push_back(u);
return;
}
if(vis[u])return;
vis[u]=1;
num++;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
find(v);
}
}
void solve(int n){
ll ans1=0,ans2=1;
int i;
for(i=1;i<=n;i++)
if(!dfn[i])
gen=i,tarjan(i,0); //////注意这里要把根指明
for(i=1;i<=n;i++){
if(cut[i]==0 && vis[i]==0){
vec.clear();
num=0;
find(i);
sort(vec.begin(),vec.end());
cutnum=unique(vec.begin(),vec.end())-vec.begin();
if(cutnum>=2)continue;
if(cutnum==1){
ans1++;
ans2*=num;
}
else{
if(num==1)
ans1++;
else{
ans1+=2;
ans2*=(num-1)*num/2;
}
}
}
}
printf("Case %d: %lld %lld\n",++cas,ans1,ans2);
}
int main(){
int k,i,n,m;
int u,v;
cas=0;
while(scanf("%d",&m)){
if(m==0)break;
init();
n=0;
for(i=1;i<=m;i++){
scanf("%d %d",&u,&v);
n=max(n,u),n=max(n,v);
addedge(u,v);
}
solve(n);
}
}