题意:
给出一个无向完全图,先在需要在图中选出最少的点,使得满足:删掉任意一个点之后,剩下的点都可以到达至少一个选择的点。求出最少选择的点数,以及选点的方案数。
题解:
显然,本题的描述本质上就是双连通性,即所有点到指定点都是点双连通的。那么考虑原图的割点
,如果一个点双
只包括一个割点
,那么如果删掉了割点,就使得这个点双与原图断开连接,因此这个点双内一定要选出一个点(不能是割点);如果一个点双
包括两个以上的割点
,那么删掉某一个割点,可以向另外一个割点的方向搜寻关键点,已知搜寻到上面那种点双内部就可以找到。因此,只需要在每个只包含一个割点的点双内的非割点中选择一个点,就是最小方案。
一种比较好的处理方法是:先找到割点,然后对每一个非割点,dfs出块的大小,和包含割点个数。
另外。。。方案数会爆int。。。LL即可
Code:
#include<bits/stdc++.h>
//#define local
using namespace std;
const int maxn = 1500+100;
const int maxm = 1e3+100;
int T;
int m,n;
int first[maxn],des[maxm*2],nxt[maxm*2],tot;
int dfn[maxn],low[maxn],dfs_clock;
bool isCut[maxn];
int vis[maxn];
int sz,cutCnt,cutTot;
void init(){
memset(first,0,sizeof first);
tot=0;
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
dfs_clock =0;
memset(isCut,0,sizeof isCut);
memset(vis,0,sizeof vis);
n=0;
cutTot=0;
}
inline void addEdge(int x,int y){
tot ++;
des[tot] =y;
nxt[tot] = first[x];
first[x] = tot;
}
void input(){
while (m--){
int u,v;
cin>>u>>v;
n = max(n,max(u,v));
addEdge(u,v);
addEdge(v,u);
}
}
void tarjan(int x,int fa){
dfn[x] = low[x] = ++dfs_clock;
int child =0;
for (int t = first[x] ;t;t=nxt[t]){
int v = des[t];
if (v==fa)continue;
if (!dfn[v]){
tarjan(v,x);
child++;
low[x] = min(low[x],low[v]);
if (low[v]>=dfn[x]&&fa!=-1||fa==-1&&child>1){
isCut[x] = 1;
}
}else if (dfn[v]<dfn[x]){
low[x] = min(low[x],dfn[v]);
}
}
}
void dfs(int x,int flag){
sz++;
vis[x] = flag;
for (int t = first[x];t;t=nxt[t]){
int v = des[t];
if (isCut[v]){
if (vis[v]!=flag)cutCnt++,vis[v] = flag;
}else if (vis[v]!=flag){
dfs(v,flag);
}
}
}
void work(){
cout<<"Case "<<T<<": ";
for (int i=1;i<=n;i++){
if (!dfn[i]){
tarjan(i,-1);
}
}
for (int i=1;i<=n;i++){
cutTot+=isCut[i];
}
if (cutTot==0){
cout<<2<<" "<<n*(n-1)/2<<endl;
return ;
}
long long ans=1;
int ans2=0;
for (int i=1;i<=n;i++){
if (!vis[i]&&!isCut[i]){
sz=cutCnt=0;
dfs(i,i);
if (cutCnt==1)ans = ans*sz,ans2++;
}
}
cout<<ans2<<" "<<ans<<endl;
}
void solve(){
init();
input();
work();
}
int main(){
#ifdef local
freopen("input.in","r",stdin);
#endif // local
for (T=1,cin>>m;m;T++,cin>>m){
solve();
}
return 0;
}