洛谷 P3225 [HNOI2012]矿场搭建
Posted 小时のblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P3225 [HNOI2012]矿场搭建相关的知识,希望对你有一定的参考价值。
题目大意:建设几个出口,使得图上无论哪个点被破坏,都可以与出口联通。
题解:tarjian求割点
首先出口不能建在割点上,找出割点,图就被分成了几个联通块。
每个联通块,建出口。如果割点数为0,建两个出口,一个炸了,
另一个还可以走,那么方案数是c(size,2),如果割点为1个,那么
随便从联通块里建一个就好,割点炸了有新建的,新建的炸了还有
割点可以走,方案数是联通块大小。注意long long
代码:
#include<iostream> #include<cstdio> #include<cstring> #define maxn 5200 #define LL long long using namespace std; int n,kis,sumedge,root,cnt,tim,head[maxn],low[maxn],dfn[maxn],iscut[maxn],vis[maxn]; LL ans=1,tmp; int cntcut,kuai; struct Edge{ int x,y,nxt; Edge(int x=0,int y=0,int nxt=0): x(x),y(y),nxt(nxt){} }edge[maxn<<1]; void add(int x,int y){ edge[++sumedge]=Edge(x,y,head[x]); head[x]=sumedge; } void Tarjian(int x,int fa){ int cnt=0;low[x]=dfn[x]=++tim; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v==fa)continue; if(dfn[v]==0){ cnt++; Tarjian(v,x); low[x]=min(low[x],low[v]); if(x!=root&&low[v]>=dfn[x]&&iscut[x]==0)iscut[x]=true; if(x==root&&cnt>=2&&iscut[x]==0)iscut[x]=true; }else low[x]=min(low[x],dfn[v]); } } void dfs(int x){ tmp++;vis[x]=kuai; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(iscut[v]&&vis[v]!=kuai)cntcut++,vis[v]=kuai; if(!vis[v])dfs(v); } } int main(){ while(1){ scanf("%d",&n); sumedge=0;tim=0;ans=1;cnt=0; kuai=0;memset(vis,0,sizeof(vis)); memset(iscut,0,sizeof(iscut)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(head,0,sizeof(head)); if(!n)break;int xr=0; for(int i=1;i<=n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y);add(y,x); xr=max(max(x,y),xr); } for(int i=1;i<=xr;i++)if(dfn[i]==0)root=i,Tarjian(i,i); for(int i=1;i<=xr;i++){ tmp=0;cntcut=0;kuai++; if(vis[i]==0&&iscut[i]==0){ dfs(i);if(cntcut==1)cnt++,ans=1LL*ans*tmp; if(cntcut==0)cnt+=2,ans=1LL*ans*tmp*(tmp-1)/2; } } printf("Case %d: %d %lld\n",++kis,cnt,ans); } return 0; }
以上是关于洛谷 P3225 [HNOI2012]矿场搭建的主要内容,如果未能解决你的问题,请参考以下文章