题解:
首先显然这是要缩点的 缩点双
直接对割点之间的联通块判断一下连着几个割点
连0个 cnt*(cnt-1)/2
连1个 cnt
连2个 0
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 2000
bool iscut[N],ff[N];
ll head[N],dfn[N],low[N],cc,now,l,num,cnt,T,color[N];
ll n,m;
struct re{
ll a,b,c;
}a[N];
void arr(ll x,ll y)
{
a[++l].a=head[x];
a[l].b=y;
head[x]=l;
}
void tarjan(ll x,ll fa)
{
dfn[x]=low[x]=++now;
ll child=0;
ll u=head[x];
while (u)
{
ll v=a[u].b;
if (!dfn[v])
{
child++;
tarjan(v,x);
low[x]=min(low[x],low[v]);
if (low[v]>=dfn[x]) iscut[x]=1;
} else
{
if (v!=fa) low[x]=min(low[x],dfn[v]);
}
u=a[u].a;
}
if (fa==0&&child==1) iscut[x]=0;
}
void dfs(ll x)
{
color[x]=cc;
if (iscut[x]) return;
ff[x]=1; cnt++;
ll u=head[x];
while (u)
{
ll v=a[u].b;
if (iscut[v]&&color[v]!=cc) num++;
if (!ff[v]) dfs(v);
u=a[u].a;
}
}
int main()
{
freopen("noi.in","r",stdin);
freopen("noi.out","w",stdout);
while (cin>>m&&m)
{
T++;
n=0; memset(head,0,sizeof(head));
now=l=0;
memset(iscut,0,sizeof(iscut));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(ff,0,sizeof(ff));
for (ll i=1;i<=m;i++)
{
ll x,y;
cin>>x>>y;
n=max(n,max(x,y));
arr(x,y); arr(y,x);
}
for (ll i=1;i<=n;i++)
if(!dfn[i]) tarjan(i,0);
ll ans=1,ans1=0;
for (ll i=1;i<=n;i++)
if (!iscut[i]&&!ff[i])
{
num=0; cnt=0; cc++;
dfs(i);
if (num==0) ans*=max(1ll,cnt*(cnt-1)/2),ans1+=min(cnt,2ll);
if (num==1) ans*=cnt,ans1++;
}
cout<<"Case "<<T<<": "<<ans1<<" "<<ans<<endl;
}
return 0;
}