您的位置:首页 > 其它

bzoj 2730: [HNOI2012]矿场搭建

2016-03-22 06:27 465 查看
#include<cstdio>
#include<cstring>
#include<iostream>
#define M 508
using namespace std;
int T=1,m,n,head[M],K,next[10*M],u[10*M],cnt,f[M],c[M],fa[M],dfn[M],low[M],time1,ans,bi[M],sum[M];
long long ans1=1;
void jia(int a1,int a2)
{
cnt++;
next[cnt]=head[a1];
head[a1]=cnt;
u[cnt]=a2;
}
void tarjin(int a1,int deep)
{
time1++;
dfn[a1]=low[a1]=time1;
c[a1]=-1;
int tot=0;
for(int i=head[a1];i;i=next[i])
if(u[i]!=fa[a1])
{
fa[u[i]]=a1;
if(!c[u[i]])
{
tarjin(u[i],deep+1);
low[a1]=min(low[a1],low[u[i]]);
tot++;
if(deep==1&&tot>1)
f[a1]=1;
if(deep>1&&low[u[i]]>=dfn[a1])
f[a1]=1;
}
else  if(c[u[i]]==-1&&u[i]!=fa[a1])
low[a1]=min(low[a1],dfn[u[i]]);
}
c[a1]=1;
}
void dfs(int a1)
{
c[a1]=1;
if(!bi[a1])
bi[a1]=time1;
else
bi[a1]=-1;
for(int i=head[a1];i;i=next[i])
if(!c[u[i]]&&!f[u[i]])
dfs(u[i]);
return;
}
int main()
{
for(;scanf("%d",&m),m;T++){
ans=cnt=n=0;
ans1=1;
memset(head,0,sizeof(head));
memset(bi,0,sizeof(bi));
memset(f,0,sizeof(f));
memset(sum,0,sizeof(sum));
for(int i=1;i<=m;i++)
{
int a1,a2;
scanf("%d%d",&a1,&a2);
n=max(n,a1);
n=max(n,a2);
jia(a1,a2);
jia(a2,a1);
}
time1=0;
for(int i=1;i<=n;i++)
{
f[i]=0;
c[i]=0;
fa[i]=0;
}
tarjin(1,1);
time1=0;
for(int i=1;i<=n;i++)
if(f[i])
{
memset(c,0,sizeof(c));
for(int j=head[i];j;j=next[j])
if(!c[u[j]]&&!f[u[j]])
{
time1++;
dfs(u[j]);
}
}
for(int i=1;i<=n;i++)
if(bi[i]!=-1)
sum[bi[i]]++;
for(int i=1;i<=time1;i++)
if(sum[i])
{
ans++;
ans1*=sum[i];
}
printf("Case %d: ",T);
if(ans)
printf("%d %lld\n",ans,ans1);
else
printf("2 %d\n",n*(n-1)/2);}
return 0;
}


先用tarjin找割点 割点条件u1是树根,且有大于1棵子树,u1不是树根,low[u[i]]>dfn[u1],把和一个割点相连的联通块建出口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: