bzoj2730 [HNOI2012] 矿场搭建

tarjan跑出来所有的割点

dfs搞每一个点双和几个割点相连,0个就要建两个,因为建一个的话,那个地方没了就死了,1个就要建一个,因为如果割点断了,需要内部供给,2个就不用建,任意一个断都可以从另一边过

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define N 1500
 7 using namespace std;
 8 int n,m,cnt,num,tot,ans1,cosmos,bo[N];
 9 long long ans2;
10 int dfn[N],low[N],judge[N],top,son,root;
11 int e=1,head[N];
12 struct edge{
13     int u,v,next;
14 }ed[5000];
15 void add(int u,int v){
16     ed[e].u=u; ed[e].v=v;
17     ed[e].next=head[u]; head[u]=e++;
18 }
19 void tarjan(int x,int f){
20     dfn[x]=low[x]=++top;
21     for(int i=head[x];i;i=ed[i].next){
22         int v=ed[i].v;
23         if(v==x) continue;
24         if(!dfn[v]){
25             tarjan(v,x);
26             low[x]=min(low[x],low[v]);
27         }
28         else{low[x]=min(low[x],dfn[v]);continue;}
29         if(dfn[x]<=low[v]){
30             if(x==root)son++;
31             else judge[x]=1;
32         }
33     }
34 }
35 void dfs(int x){
36     bo[x]=tot;
37     if(judge[x]) return;cnt++;
38     for(int i=head[x];i;i=ed[i].next){
39         int v=ed[i].v;
40         if(judge[v]&&bo[v]!=tot){num++;bo[v]=tot;}
41         if(!bo[v])dfs(v);
42     }
43 }
44 void init(){
45     memset(dfn,0,sizeof dfn);
46     memset(low,0,sizeof low);
47     memset(judge,0,sizeof judge);
48     memset(bo,0,sizeof bo); cosmos++;
49     n=0; ans1=0; ans2=1; tot=0; top=0;
50     e=1; memset(head,0,sizeof head);
51 }
52 int main(){
53     while(scanf("%d",&m)==1&&m!=0){
54         init();
55         int u,v;
56         for(int i=1;i<=m;i++){
57             scanf("%d%d",&u,&v);
58             n=max(n,max(u,v));
59             add(u,v); add(v,u);
60         }
61         for(int i=1;i<=n;i++){
62             if(!dfn[i]){
63                 son=0; root=i; 
64                 tarjan(i,0);
65                 if(son>1) judge[i]=1;
66             }
67         }
68         /*for(int i=1;i<=n;i++)
69             printf("%d  %d\n",i,judge[i]);*/
70         for(int i=1;i<=n;i++){
71             if(!bo[i]&&!judge[i]){
72                 tot++;cnt=num=0;
73                 dfs(i);
74                 if(!num){ans1+=2;ans2*=cnt*(cnt-1)/2;}
75                 if(num==1){ans1++;ans2*=cnt;}
76                 //printf("%d  %d  %d  %d\n",i,tot,cnt,num);
77             }
78         }
79         printf("Case %d: %d %lld\n",cosmos,ans1,ans2);
80     }
81     return 0;
82 }
View Code

 

posted @ 2017-08-20 18:09  Ren_Ivan  阅读(137)  评论(0编辑  收藏  举报