首先不难想到要先求割顶,求割顶的方法白书上有讲解
由于是一个矿崩塌,所以假如一个连通块连接了两个以上割顶,那么这个连通块内显然是不用设出口的
连接块只连接了一个割顶,那么出口可以设在这个连通块内任意位置
由此我们可以把两个问题解决了
注意特判一种情况,当不存在割顶的时候,至少要设两个出口

  1 type node=record
  2        po,next:longint;
  3      end;
  4 
  5 var w:array[0..500010] of node;
  6     dfn,low,mark,cs,s,p:array[0..510] of longint;
  7     v,cut:array[0..510] of boolean;
  8     task,tot,t,i,x,y,len,n,m:longint;
  9     ans:int64;
 10 
 11 function min(a,b:longint):longint;
 12   begin
 13     if a>b then exit(b) else exit(a);
 14   end;
 15 
 16 procedure add(x,y:longint);
 17   begin
 18     inc(len);
 19     w[len].po:=y;
 20     w[len].next:=p[x];
 21     p[x]:=len;
 22   end;
 23 
 24 procedure dfs(x,fa:longint);
 25   var i,y,ch:longint;
 26   begin
 27     inc(t);
 28     dfn[x]:=t;
 29     low[x]:=t;
 30     i:=p[x];
 31     ch:=0;
 32     while i<>-1 do
 33     begin
 34       y:=w[i].po;
 35       if dfn[y]=0 then
 36       begin
 37         dfs(y,x);
 38         inc(ch);
 39         low[x]:=min(low[x],low[y]);
 40         if low[y]>=dfn[x] then cut[x]:=true;  //只要有子树不能连回当前点的祖先
 41       end
 42       else if (dfn[y]<dfn[x]) and (fa<>y) then  //注意fa<>y
 43         low[x]:=min(low[x],dfn[y]);
 44       i:=w[i].next;
 45     end;
 46     if (fa<0) and (ch=1) then cut[x]:=false; //注意单链的首位不是割顶
 47   end;
 48 
 49 procedure color(x:longint);
 50   var i,y:longint;
 51   begin
 52     i:=p[x];
 53     v[x]:=true;
 54     inc(s[t]);
 55     while i<>-1 do
 56     begin
 57       y:=w[i].po;
 58       if not v[y] then
 59       begin
 60         if not cut[y] then color(y)
 61         else if mark[y]<>t then
 62         begin
 63           mark[y]:=t;
 64           inc(cs[t]);
 65         end;
 66       end;
 67       i:=w[i].next;
 68     end;
 69   end;
 70 
 71 begin
 72   readln(m);
 73   while m<>0 do
 74   begin
 75     inc(task);
 76     len:=-1;
 77     fillchar(p,sizeof(p),255);
 78     n:=0;
 79     for i:=1 to m do
 80     begin
 81       readln(x,y);
 82       add(x,y);
 83       add(y,x);
 84       if x>n then n:=x;
 85       if y>n then n:=y;
 86     end;
 87     fillchar(dfn,sizeof(dfn),0);
 88     fillchar(cut,sizeof(cut),false);
 89     for i:=1 to n do
 90       if dfn[i]=0 then
 91       begin
 92         t:=0;
 93         dfs(i,-1);
 94       end;
 95     ans:=1;
 96     t:=0;
 97     tot:=0;
 98     fillchar(v,sizeof(v),false);
 99     fillchar(mark,sizeof(mark),0);
100     fillchar(cs,sizeof(cs),0);
101     for i:=1 to n do
102       if not v[i] and not cut[i] then
103       begin
104         inc(t);
105         s[t]:=0;
106         color(i);
107         if cs[t]=1 then
108         begin
109           inc(tot);
110           ans:=ans*int64(s[t]);
111         end;
112       end;
113     if t=1 then  //特判
114     begin
115       tot:=2;
116       ans:=n*(n-1) div 2;
117     end;
118     writeln('Case ',task,': ',tot,' ',ans);
119     readln(m);
120   end;
121 end.
View Code

 

posted on 2014-11-07 16:39  acphile  阅读(106)  评论(0编辑  收藏  举报