cogs1348 矿场搭建 求割点
Posted Loser Of Life
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 矿场搭建 求割点的主要内容,如果未能解决你的问题,请参考以下文章