首页 > 代码库 > cogs1348 矿场搭建 求割点

cogs1348 矿场搭建 求割点

继续填坑……链接:http://cogs.pro/cogs/problem/problem.php?pid=1348

题意:求出最小逃生出口数量,使得无论哪个点被切断其他点都可以继续与其他出口联通。

首先看题面就知道,这个点一定不能存在于割点上。那么我们就先求一遍割点。求完之后,我们就切断割点与卡拉其他点的连接,再从每个点开始$dfs$,每个连通分量都走一下,当且仅当这个连通分量经过一个割点时数量才加1,方案数增加非割点数。

作为一种特殊情况,全图没有割点时,需要建两个出口,方案为$(n-1)*n/2$。

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn=505;
 7 struct node
 8 {
 9     int from,to,next;
10 }edge[maxn<<1];
11 int head[maxn],tot;
12 void addedge(int u,int v)
13 {
14     edge[++tot]=(node){u,v,head[u]};head[u]=tot;
15 }
16 int n,m;
17 int dfn[maxn],low[maxn],cnt,belong[maxn],scnt,rt,son;
18 bool iscut[maxn],exist[maxn];
19 void tarjan1(int root)
20 {
21     low[root]=dfn[root]=++cnt;
22     for(int i=head[root];i;i=edge[i].next)
23     {
24         int v=edge[i].to;
25         if(!dfn[v])
26         {
27             tarjan1(v);
28             if(root==rt)son++;
29             else
30             {
31                 low[root]=min(low[root],low[v]);
32                 if(low[v]>=dfn[root]&&!iscut[root])iscut[root]=1;
33             }
34         }
35         else low[root]=min(low[root],dfn[v]);
36     }
37 }
38 int tcnt,vis[maxn];
39 void dfs(int root)
40 {
41     exist[root]=0;
42     for(int i=head[root];i;i=edge[i].next)
43     {
44         int v=edge[i].to;
45         if(!exist[v])continue;
46         if(iscut[v]&&vis[v]!=tcnt)vis[v]=tcnt,cnt++;
47         else if(!iscut[v])scnt++,dfs(v);
48     }
49 }
50 int haha()
51 {
52     //freopen("bzoj_2730.in","r",stdin);
53     //freopen("bzoj_2730.out","w",stdout);
54     int kases=1;
55     while(scanf("%d",&n)!=EOF&&n)
56     {
57         m=scnt=tot=cnt=0;memset(head,0,sizeof(head));
58         memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));
59         memset(head,0,sizeof(head));memset(iscut,0,sizeof(iscut));
60         memset(exist,0,sizeof(exist));
61         for(int i=1;i<=n;i++)
62         {
63             int x,y;scanf("%d%d",&x,&y);
64             addedge(x,y);addedge(y,x);
65             if(!exist[x])exist[x]=1,m=max(m,x);
66             if(!exist[y])exist[y]=1,m=max(m,y);
67         }
68         for(int i=1;i<=m;i++)
69             if(!dfn[i]&&exist[i])
70             {
71                 rt=i;
72                 son=0;
73                 tarjan1(i);
74                 if(son>1&&!iscut[i])iscut[i]=1;
75             }
76         long long ans=0,way=1;
77         for(int i=1;i<=m;i++)
78         {
79             if(!exist[i])continue;
80             if(!iscut[i])
81             {
82                 cnt=0;scnt=1;tcnt++;dfs(i);
83                 if(!cnt)ans+=2,way*=1ll*scnt*(scnt-1)/2;
84                 else if(cnt==1)ans++,way*=1ll*scnt;
85             }
86         }
87         printf("Case %d: %lld %lld\n",kases++,ans,way);
88     }
89 }
90 int sb=haha();
91 int main(){;}
cogs1348

 

cogs1348 矿场搭建 求割点