1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define M 508 5 using namespace std; 6 int T=1,m,n,head[M],K,next[10*M],u[10*M],cnt,f[M],c[M],fa[M],dfn[M],low[M],time1,ans,bi[M],sum[M]; 7 long long ans1=1; 8 void jia(int a1,int a2) 9 { 10 cnt++; 11 next[cnt]=head[a1]; 12 head[a1]=cnt; 13 u[cnt]=a2; 14 } 15 void tarjin(int a1,int deep) 16 { 17 time1++; 18 dfn[a1]=low[a1]=time1; 19 c[a1]=-1; 20 int tot=0; 21 for(int i=head[a1];i;i=next[i]) 22 if(u[i]!=fa[a1]) 23 { 24 fa[u[i]]=a1; 25 if(!c[u[i]]) 26 { 27 tarjin(u[i],deep+1); 28 low[a1]=min(low[a1],low[u[i]]); 29 tot++; 30 if(deep==1&&tot>1) 31 f[a1]=1; 32 if(deep>1&&low[u[i]]>=dfn[a1]) 33 f[a1]=1; 34 } 35 else if(c[u[i]]==-1&&u[i]!=fa[a1]) 36 low[a1]=min(low[a1],dfn[u[i]]); 37 } 38 c[a1]=1; 39 } 40 void dfs(int a1) 41 { 42 c[a1]=1; 43 if(!bi[a1]) 44 bi[a1]=time1; 45 else 46 bi[a1]=-1; 47 for(int i=head[a1];i;i=next[i]) 48 if(!c[u[i]]&&!f[u[i]]) 49 dfs(u[i]); 50 return; 51 } 52 int main() 53 { 54 for(;scanf("%d",&m),m;T++){ 55 ans=cnt=n=0; 56 ans1=1; 57 memset(head,0,sizeof(head)); 58 memset(bi,0,sizeof(bi)); 59 memset(f,0,sizeof(f)); 60 memset(sum,0,sizeof(sum)); 61 for(int i=1;i<=m;i++) 62 { 63 int a1,a2; 64 scanf("%d%d",&a1,&a2); 65 n=max(n,a1); 66 n=max(n,a2); 67 jia(a1,a2); 68 jia(a2,a1); 69 } 70 time1=0; 71 for(int i=1;i<=n;i++) 72 { 73 f[i]=0; 74 c[i]=0; 75 fa[i]=0; 76 } 77 tarjin(1,1); 78 time1=0; 79 for(int i=1;i<=n;i++) 80 if(f[i]) 81 { 82 memset(c,0,sizeof(c)); 83 for(int j=head[i];j;j=next[j]) 84 if(!c[u[j]]&&!f[u[j]]) 85 { 86 time1++; 87 dfs(u[j]); 88 } 89 } 90 for(int i=1;i<=n;i++) 91 if(bi[i]!=-1) 92 sum[bi[i]]++; 93 for(int i=1;i<=time1;i++) 94 if(sum[i]) 95 { 96 ans++; 97 ans1*=sum[i]; 98 } 99 printf("Case %d: ",T); 100 if(ans) 101 printf("%d %lld\n",ans,ans1); 102 else 103 printf("2 %d\n",n*(n-1)/2);} 104 return 0; 105 }
先用tarjin找割点 割点条件u1是树根,且有大于1棵子树,u1不是树根,low[u[i]]>dfn[u1],把和一个割点相连的联通块建出口。