题解:
首先显然这是要缩点的 缩点双
直接对割点之间的联通块判断一下连着几个割点
连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;
}