bzoj2730(矿场搭建)

矿场搭建,不知道为什么,莫名其妙T了在212上,额,zyh数据真的坑。

bzoj200轻松跑过啊。

就是点双联通分量缩点,然后标记割点,一个块如果有>=2个割点,则不需要挖矿洞,

如果只有一割点,就乘以改块的大小-1

如果无割点,则乘以C(size,2);

  1 #include<cstdio>    
  2 #include<cstring>    
  3 #include<iostream>    
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<vector>
  7 using namespace std;
  8     
  9 typedef long long ll;
 10 const int NN=50007;
 11     
 12 int n,m;
 13 int tim,top,root,scc;
 14 int cnt,head[NN],rea[NN*2],next[NN*2];
 15 int dfn[NN],low[NN],q[NN],instack[NN],gedian[NN],num[NN];
 16 vector<int>a[NN];
 17 
 18 void init()
 19 {
 20     n=tim=top=scc=0;
 21     memset(head,-1,sizeof(head));
 22     memset(dfn,0,sizeof(dfn));
 23     memset(gedian,0,sizeof(gedian));
 24     memset(num,0,sizeof(num));
 25 }
 26 void add(int u,int v)
 27 {
 28     cnt++;
 29     next[cnt]=head[u];
 30     head[u]=cnt;
 31     rea[cnt]=v;
 32 }
 33 void Tarjan(int u,int fa)
 34 {
 35     int num=0;
 36     dfn[u]=low[u]=++tim;
 37     q[++top]=u,instack[u]=1;
 38     for (int i=head[u];i!=-1;i=next[i])
 39     {
 40         int v=rea[i];
 41         if (v==fa) continue;
 42         if (dfn[v]==0)
 43         {
 44             Tarjan(v,u);
 45             low[u]=min(low[u],low[v]);
 46             num++;
 47             if (u==root&&num>1) gedian[u]=1;
 48             else if (u!=root&&low[v]>=dfn[u]) gedian[u]=1;
 49             if (low[v]>=dfn[u])
 50             {
 51                 scc++;
 52                 a[scc].clear();
 53                 int x=-1;
 54                 while (x!=u)
 55                 {
 56                     x=q[top--];
 57                     instack[x]=0;
 58                     a[scc].push_back(x);
 59                 }
 60                 q[++top]=u,instack[u]=1;
 61             }
 62         }
 63         else low[u]=min(low[u],dfn[v]);
 64     }
 65 }
 66 long long c(int n,int m)
 67 {
 68     long long res=n*(n-1)/2;
 69     return res;
 70 }
 71 int main()
 72 {
 73     int fzy=0;
 74     while(scanf("%d",&m)&&m)
 75     {
 76         fzy++;
 77         init();
 78         int x,y;
 79         for (int i=1;i<=m;i++)
 80         {
 81             scanf("%d%d",&x,&y);
 82             add(x,y),add(y,x);
 83             n=max(x,n),n=max(y,n);
 84         }
 85         for (int i=1;i<=n;i++)
 86             if (dfn[i]==0)
 87             {
 88                 root=i;
 89                 Tarjan(i,-1);
 90             }
 91         for (int i=1;i<=scc;i++)
 92             for (int j=0;j<a[i].size();j++)
 93                 if (gedian[a[i][j]]) num[i]++;
 94         long long ans1=0,ans2=1;
 95         for (int i=1;i<=scc;i++)
 96         {
 97             if (num[i]==0)
 98             {
 99                 ans1+=2;
100                 ans2*=c(a[i].size(),2);
101             }
102             else if (num[i]==1)
103                  {
104                       ans1+=1;
105                       ans2*=a[i].size()-1;
106                  }
107         }        
108         printf("Case %d: %lld %lld\n",fzy,ans1,ans2);    
109     }
110     return 0;
111 }

 

posted @ 2017-08-25 21:17  Kaiser-  阅读(303)  评论(0编辑  收藏  举报