码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 2730: [HNOI2012]矿场搭建

时间:2016-03-22 07:51:53      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #define M 508
  5 using namespace std;
  6 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];
  7 long long ans1=1;
  8 void jia(int a1,int a2)
  9 {
 10     cnt++;
 11     next[cnt]=head[a1];
 12     head[a1]=cnt;
 13     u[cnt]=a2;
 14 }
 15 void tarjin(int a1,int deep)
 16 {
 17     time1++;
 18     dfn[a1]=low[a1]=time1;
 19     c[a1]=-1;
 20     int tot=0;
 21     for(int i=head[a1];i;i=next[i])
 22     if(u[i]!=fa[a1])
 23       {
 24         fa[u[i]]=a1;
 25         if(!c[u[i]])
 26           {
 27             tarjin(u[i],deep+1);
 28             low[a1]=min(low[a1],low[u[i]]);
 29             tot++;
 30             if(deep==1&&tot>1)
 31               f[a1]=1;
 32             if(deep>1&&low[u[i]]>=dfn[a1])
 33               f[a1]=1;
 34           }
 35         else  if(c[u[i]]==-1&&u[i]!=fa[a1])
 36                  low[a1]=min(low[a1],dfn[u[i]]);
 37       }
 38     c[a1]=1;
 39 }
 40 void dfs(int a1)
 41 {
 42     c[a1]=1;
 43     if(!bi[a1])
 44       bi[a1]=time1;
 45     else
 46       bi[a1]=-1;
 47     for(int i=head[a1];i;i=next[i])
 48       if(!c[u[i]]&&!f[u[i]])
 49         dfs(u[i]);
 50     return;
 51 }
 52 int main()
 53 {
 54     for(;scanf("%d",&m),m;T++){
 55     ans=cnt=n=0;
 56     ans1=1;
 57     memset(head,0,sizeof(head));
 58     memset(bi,0,sizeof(bi));
 59     memset(f,0,sizeof(f));
 60     memset(sum,0,sizeof(sum));
 61     for(int i=1;i<=m;i++)
 62       {
 63         int a1,a2;
 64         scanf("%d%d",&a1,&a2);
 65         n=max(n,a1);
 66         n=max(n,a2);
 67         jia(a1,a2);
 68         jia(a2,a1);
 69       }
 70     time1=0;
 71     for(int i=1;i<=n;i++)
 72       {
 73          f[i]=0;
 74          c[i]=0;
 75          fa[i]=0;
 76       }
 77     tarjin(1,1);
 78     time1=0;
 79     for(int i=1;i<=n;i++)
 80       if(f[i])
 81         {
 82           memset(c,0,sizeof(c));
 83           for(int j=head[i];j;j=next[j])
 84             if(!c[u[j]]&&!f[u[j]])
 85               {
 86                 time1++;
 87                 dfs(u[j]);
 88               }
 89         }
 90     for(int i=1;i<=n;i++)
 91       if(bi[i]!=-1)
 92         sum[bi[i]]++;
 93     for(int i=1;i<=time1;i++)
 94       if(sum[i])
 95         {
 96             ans++;
 97             ans1*=sum[i];
 98         }
 99     printf("Case %d: ",T);
100     if(ans)
101       printf("%d %lld\n",ans,ans1);
102     else
103       printf("2 %d\n",n*(n-1)/2);}
104     return 0;
105 }

先用tarjin找割点 割点条件u1是树根,且有大于1棵子树,u1不是树根,low[u[i]]>dfn[u1],把和一个割点相连的联通块建出口。

bzoj 2730: [HNOI2012]矿场搭建

标签:

原文地址:http://www.cnblogs.com/xydddd/p/5304569.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!