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 }
时间: 2024-12-27 09:14:34

bzoj2730的相关文章

【bzoj2730】 HNOI2012—矿场搭建

http://www.lydsy.com/JudgeOnline/problem.php?id=2730 (题目链接) 题意 给出一张图,问如果删掉其中一个点,使得其他每个节点都有一个安全撤离的出口,最少需要设立多少个出口,有多少种方案. Solution 很明显,一张图至少要设立2个出口(一个点双连通分量),如果删掉不是割点的点,对答案不会有什么限制,考虑删掉的点是割点. 我们对割点以外的联通快进行染色,每一种颜色就表示在这些同样的颜色中的节点至少要设置一个出口,若一个节点被染成了多种颜色,那

[POJ1144][BZOJ2730]tarjan求割点

求割点 一种显然的n^2做法: 枚举每个点,去掉该点连出的边,然后判断整个图是否联通 用tarjan求割点: 分情况讨论 如果是root的话,其为割点当且仅当下方有两棵及以上的子树 其他情况 设当前节点为u,一个儿子节点为v 存在low[v]>=dfn[u],也就是说其儿子节点v能连到的最前面的点都在u的下面 也就是当u断开的时候,u之前的点与以v为根的子树必然分成两个独立的块 那么这个时候u就是割点 Network A Telephone Line Company (TLC) is estab

[BZOJ2730][HNOI2012]矿场搭建(求割点)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2730 分析: 如果坍塌的点不是割点,那没什么影响,主要考虑坍塌的点是割点的情况. 显然我们可以先求出所有割点把整个图分成若干个连通块 如果一个联通块只与一个割点相连,说明我们必须在这个连通块中选一个点作为出口 如果一个联通块与两个以上的割点相连,那么就可以不在这些点取一个作为出口 方案数就是要取点的联通块的点的个数的乘积 注意没有割点的情况要放2个点

【BZOJ-2730】矿场搭建 Tarjan 双连通分量

2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1602  Solved: 751[Submit][Status][Discuss] Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用

bzoj2730: [HNOI2012]矿场搭建

Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数. Input 输入文件有若干组数据,每组数据的第一行是一个正整数 N(N≤500),表示工地的隧道数,接下来的 N 行每行是用空格隔开的两个整数 S 和 T

【双连通分量】Bzoj2730 HNOI2012 矿场搭建

Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数. Sulotion 坍塌的不是割顶并不影响,建在割顶也没有意义(拆割顶) 考虑每一个双连通分量,如果只连一个割顶必须内部建一个(随便选一个),连两个以上可以

BZOJ2730 矿场搭建 解题报告 点双联通分量

题意概述: 一张有向图,在其中设置一些关键点(即题目中的逃生出口),使得删除任意一个点之后其余点都可以到达至少一个关键点. 问至少需要设置多少中关键点,有多少种设置方法. 解析: 首先,这道题要求删掉一个点,不难想到这道题与割点有关.其次,删掉一个点其他点仍然可以到达关键点就可以想到是点双联通分量. 但是,问题关键是,真的需要在每一个点双联通分量中都设置一个关键点吗? 答案是否定的,因为如果一个双联通分量连接了两个或两个以上的割点,一个割点被删掉那么还可以通过另外的割点到达某个关键点,如上图,红

【搭楼】大力开刷图论

写在前面 继前半个月的刷杂题后,学OI的感觉找到了些,于是来刷专题吧! 感觉我接触图论到现在也有一个学期了,然而感觉我还没有系统地搞过图论或者说我是一个图论还没有入门的人>.< 刷图论主要做三件事: ①大白大白: ②BzojBzoj: ③紫书的习题: 我理想的进度安排是: 6.4-6.10搞完除网络流部分,然后开刷网络流,因为现在还没有开始网络流也不知道是什么情况. 知识刷的顺序就按照大白的来. 图的连通 ——DFS遍历,割顶,桥,双连通分量,强连通分量 DFS遍历 DFS的神奇之处是什么呢,

[转载]hzwer的bzoj题单

counter: 664BZOJ1601 BZOJ1003 BZOJ1002 BZOJ1192 BZOJ1303 BZOJ1270 BZOJ3039 BZOJ1191 BZOJ1059 BZOJ1202 BZOJ1051 BZOJ1001 BZOJ1588 BZOJ1208 BZOJ1491 BZOJ1084 BZOJ1295 BZOJ3109 BZOJ1085 BZOJ1041 BZOJ1087 BZOJ3038 BZOJ1821 BZOJ1076 BZOJ2321 BZOJ1934 BZOJ