2730: [HNOI2012]矿场搭建
求出割点,删掉后求只与一个割点相连的连通分量的个数,这就是答案。 方案数用乘法原理求就行了。 注意:只有一个连通分量时要特判。
RunID | User | Problem | Result | Memory | Time | Language | Code_Length | Submit_Time |
388096 | lbz007 | 2730 | Accepted | 228 kb | 0 ms | Pascal/Edit | 1668 B | 2013-04-10 14:42:48 |
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
[toggle title="code"] [pascal] var m,n,du,ttt,tot,u,v,i,j,color,ee:longint; c,num,ll,size,pre,head,next,e:array[1..1000]of longint; vv,cut:Array[1..1000]of boolean; an,ans:int64; function min(aa,bb:longint):longint; begin if aa<bb then exit(aa) else exit(bb); end; procedure dfs(u:longint); var j:longint; begin c[u]:=color; inc(size[color]); vv[u]:=true; j:=head[u]; while j<>0 do begin if not vv[e[j]] then begin if cut[e[j]] then begin inc(num[color]); vv[e[j]]:=true; end else dfs(e[j]); end; j:=next[j]; end; end; procedure dfsgd(u:longint); var j:longint; begin inc(tot);ll[u]:=tot;pre[u]:=tot; j:=head[u]; while j<>0 do begin if not vv[j] then begin vv[j]:=true; vv[(j+1) xor 1-1]:=true; if pre[e[j]]=0 then begin dfsgd(e[j]); ll[u]:=min(ll[u],ll[e[j]]); if u=1 then inc(du); if ll[e[j]]>=pre[u] then cut[u]:=true; end else ll[u]:=min(ll[u],pre[e[j]]); end; j:=next[j]; end; end; procedure add(u,v:longint); begin inc(ee); e[ee]:=v;next[ee]:=head[u];head[u]:=ee; end; procedure init; begin inc(ttt);tot:=0; fillchar(pre,sizeof(pre),0); fillchar(ll,sizeof(ll),0); fillchar(head,sizeof(head),0); color:=0;n:=0;ans:=0;du:=0; fillchar(size,sizeof(size),0); fillchar(num,sizeof(num),0); fillchar(c,sizeof(c),0); fillchar(vv,sizeof(vv),false); fillchar(cut,sizeof(cut),false); end; begin readln(m); while m<>0 do begin init; for i:=1 to m do begin readln(u,v); add(u,v);add(v,u); if not vv[u] then inc(n); if not vv[v] then inc(n); vv[u]:=true;vv[v]:=true; end; fillchar(vv,sizeof(vv),false); dfsgd(1); if du>1 then cut[1]:=true else cut[1]:=false; for i:=1 to n do if (not cut[i])and(c[i]=0) then begin inc(color); size[color]:=0; fillchar(vv,sizeof(vv),false); dfs(i); end; an:=1; if color=1 then begin ans:=2; an:=(n-1)*n div 2; end else for i:=1 to color do if num[i]<=1 then begin inc(ans); an:=an*size[i]; end; writeln('Case ',ttt,': ',ans,' ',an); readln(m); end; end. [/pascal] [/toggle]
-------------------------------------------------------------------------
花有重开日,人无再少年