BZOJ2730: [HNOI2012]矿场搭建
Posted Blue233333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2730: [HNOI2012]矿场搭建相关的知识,希望对你有一定的参考价值。
n<=500条边的图,求:最少设置多少关键点,使得当任意某一个点不能经过时其他点都至少能到达一个关键点,并输出方案数。
tarjan求点双,如果一个点双里面没有割点,那这就是一个孤立的点双分量,至少要设置两个点。如果有割点,大概是这样的情况:
红色的这些“叶子”分量,也就是只有一个割点的分量,是一定要设置一个关键点的,因为如果唯一的割点走不了了,这个分量的点就只能在分量里面活动了,而这样也可以使其他有多个割点的分量可以在一个割点被破坏时到达其他的关键点。方案数就乘上这些分量的大小-1即可。
在一个块里选两个点的方案记得除以2。。。。。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 //#include<assert.h> 6 #include<math.h> 7 //#include<iostream> 8 using namespace std; 9 10 int n,m; 11 #define maxn 1011 12 #define maxm 2011 13 int id[maxn],cntid; 14 struct Edge{int to,next;}edge[maxm];int first[maxn],le; 15 int getid(int x) {if (id[x]) return id[x];return (id[x]=++cntid);} 16 void in(int x,int y) {Edge &e=edge[le];e.to=y;e.next=first[x];first[x]=le++;} 17 void insert(int x,int y) {in(x,y);in(y,x);} 18 int low[maxn],dfn[maxn],Time,tot,bel[maxn],size[maxn],cut[maxn],sta[maxm],top;bool iscut[maxn]; 19 void tarjan(int x,int fa) 20 { 21 low[x]=dfn[x]=++Time; 22 int son=0; 23 for (int i=first[x];i;i=edge[i].next) 24 { 25 Edge &e=edge[i]; 26 if (!dfn[e.to]) 27 { 28 sta[++top]=i; 29 son++; 30 tarjan(e.to,x); 31 low[x]=min(low[x],low[e.to]); 32 if (low[e.to]>=dfn[x]) 33 { 34 iscut[x]=1;tot++;size[tot]=cut[tot]=0; 35 for (;;) 36 { 37 int u=edge[sta[top]].to,v=edge[sta[top]^1].to; 38 if (bel[u]!=tot) bel[u]=tot,size[tot]++,cut[tot]+=iscut[u]; 39 if (bel[v]!=tot) bel[v]=tot,size[tot]++,cut[tot]+=iscut[v]; 40 top--; 41 if (v==x && u==e.to) break; 42 } 43 } 44 } 45 else if (e.to!=fa && dfn[e.to]<dfn[x]) 46 { 47 sta[++top]=i; 48 low[x]=min(low[x],dfn[e.to]); 49 } 50 } 51 if (!fa && son<=1) iscut[x]=0,cut[bel[x]]--; 52 } 53 void tarjan() 54 { 55 memset(dfn,0,sizeof(dfn)); 56 memset(bel,0,sizeof(bel)); 57 memset(iscut,0,sizeof(iscut)); 58 Time=tot=top=0; 59 for (int i=1;i<=n;i++) 60 if (!dfn[i]) tarjan(i,0); 61 } 62 #define LL long long 63 int main() 64 { 65 int x,y,Case=0; 66 while (scanf("%d",&n) && n) 67 { 68 cntid=0;le=2; 69 memset(first,0,sizeof(first)); 70 memset(id,0,sizeof(id)); 71 for (int i=1;i<=n;i++) 72 { 73 scanf("%d%d",&x,&y); 74 x=getid(x),y=getid(y); 75 insert(x,y); 76 } 77 m=n;n=cntid; 78 tarjan(); 79 LL ans=1,sum=0; 80 for (int i=1;i<=tot;i++) 81 { 82 if (!cut[i]) sum+=2,ans=ans*size[i]*(size[i]-1)/2; 83 else if (cut[i]==1) sum++,ans=ans*(size[i]-1); 84 } 85 printf("Case %d: %lld %lld\\n",++Case,sum,ans); 86 } 87 return 0; 88 }
以上是关于BZOJ2730: [HNOI2012]矿场搭建的主要内容,如果未能解决你的问题,请参考以下文章