【题目大意】

煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。

【思路】

可以得出这样的结论:

(1)如果一个点是割点,那么在它上面建救援出口是没有意义的

(2)对于出去割点后的连通块,如果它和两个及以上的割点相连,这不需要建救援出口;否则要建一个救援出口,在连通块里选任意一个即可,最终方案数为这些连通块大小的乘积。

(3)如果只有一个联通块,那么至少建两个救援出口,最终方案书为(size)*(size-1)/2。

所以这样做:

首先用tarjan求出割点并记录,然后跑dfs求出除去割点后的连通块的个数和大小,再依据上述结论输出答案。

【错误点】

数组从0开始和从1开始搞错了一次..判断连通块周围割点的个数的时候弄错了…具体见注释

一开始忘记清空vector,后来发现用clear清空的话会RE。请教之后才知道vector清空的正确方式长成这个样子:vector<int>().swap(E[i])

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=+;
vector<int> E[MAXN];
int kase=;
int n,m;//隧道的数量和矿井的数量
int dfn[MAXN],low[MAXN],vis[MAXN];
int cut[MAXN],cnt;//记录每一个点是否是割点以及连通块的总数
int nearcut[MAXN],size[MAXN];//当前连通块可以到达的割点数量&每个连通块的大小
int t;
int viscut[MAXN]; int tarjan(int isrt,int u)
{
vis[u]=;
dfn[u]=low[u]=++t;
int sonnum=;
for (int i=;i<E[u].size();i++)
{
int son=E[u][i];
if (!vis[son])
{
sonnum++;
tarjan(,son);
low[u]=min(low[u],low[son]);
if (isrt && sonnum>=) cut[u]=;//如果是根节点,且孩子的数量大于等于两个,则是割点
if (!isrt && dfn[u]<=low[son]) cut[u]=; //如果不是根节点,并且孩子的low大于等于当前的dfn,即没有走到过u之前,则是割点
}
else
low[u]=min(low[u],dfn[son]);
}
} void dfs(int u)
{
vis[u]=;
size[cnt]++;
for (int i=;i<E[u].size();i++)
{
int son=E[u][i];
if (!vis[son])
if (cut[son])
{
if (viscut[son]!=cnt)
{
//错误点:我一开始直接cnt++了,但是这样是不对的,会导致同一个割点被多次累加
nearcut[cnt]++;
viscut[son]=cnt;
}
}
else dfs(son);
}
} void init()
{
for (int i=;i<MAXN;i++) vector<int>().swap(E[i]);
m=;
for (int i=;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
E[u].push_back(v);
E[v].push_back(u);
m=max(m,max(u,v));//记下总共的矿井数量
}
} void solve()
{
memset(vis,,sizeof(vis));
memset(cut,,sizeof(cut));
memset(size,,sizeof(size));
memset(viscut,,sizeof(viscut));
t=;
for (int i=;i<=m;i++)//错误点:数组都要从1开始
{
if (vis[i]==)
tarjan(,i);//依次找出所有的割点
}
memset(vis,,sizeof(vis));
cnt=;
for (int i=;i<=m;i++)
if (!cut[i] && !vis[i])
{
cnt++;
nearcut[cnt]=;
dfs(i);
}
} void output()
{
printf("Case %d: ",kase);
if (cnt==)
{
printf("2 %lld\n",(long long)m*(m-)/);
return;
} long long tot=;
long long ans=;
if (cnt>)
{
for (int i=;i<=cnt;i++)
{
if (nearcut[i]==)
{
tot++;
ans*=size[i];
}
}
printf("%lld %lld\n",tot,ans);
}
} int main()
{
for(;;)
{
scanf("%d",&n);
if (n==) break;
kase++;
init();
solve();
output();
}
return ;
}

【tarjan求割顶】BZOJ2730-[HNOI2012]矿场搭建的更多相关文章

  1. bzoj2730 [HNOI2012]矿场搭建 (UVAlive5135 Mining Your Own Business)

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1147  Solved: 528[Submit][Statu ...

  2. [BZOJ2730][HNOI2012]矿场搭建 点双 割点

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2852  Solved: 1344[Submit][Stat ...

  3. BZOJ2730——[HNOI2012]矿场搭建

    bzoj2730 & world final 2011 H 1.题目大意:就是有一个无向图,让你在里面选择点,使得,无论哪个点没了以后,其他的点都能到达你选择的任何一个点,输出最少 选择几个点 ...

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

    Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...

  5. BZOJ2730 [HNOI2012]矿场搭建 - Tarjan割点

    Solution 输入中没有出现过的矿场点是不用考虑的, 所以不用考虑只有 一个点 的点双联通分量. 要使某个挖矿点倒塌, 相当于割去这个点, 所以我们求一遍割点和点双联通分量. 之后的点双联通分量构 ...

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

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2730 分析: 如果坍塌的点不是割点,那没什么影响,主要考虑坍塌的点是割点的情况. 显然 ...

  7. BZOJ2730: [HNOI2012]矿场搭建

    传送门 图的连通性相关的必和割点割边之类的有关. 题目要求对于一个无向图,任意一点被删除后,所有点都和某些指定点是联通的. 这道题比较简单的做法就是求出来所有的块.对于一个块,如果块里有两个及两个以上 ...

  8. [BZOJ2730]:[HNOI2012]矿场搭建(塔尖)

    题目传送门 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个 ...

  9. Tarjan水题系列(2):HNOI2012 矿场搭建

    题目: 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后 ...

随机推荐

  1. E. Intercity Travelling

    E. Intercity Travelling time limit per test 1.5 seconds memory limit per test 256 megabytes input st ...

  2. BZOJ1040 骑士 基环外向树

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6421  Solved: 2544[Submit][Status ...

  3. jwplayer 部署方案1

    <body> <div id="my_player" data_src="http://xx.com/jwplayer/uploads/test.mp4 ...

  4. iOS 之持久化存储 plist、NSUserDefaults、NSKeyedArchiver、数据库

    1.什么是持久化? 本人找了好多文章都没有找到满意的答案,最后是从孙卫琴写的<精通Hibernate:Java对象持久化技术详解>中,看到如下的解释,感觉还是比较完整的.摘抄如下: 狭义的 ...

  5. Spring - IoC(1): Spring 容器

    BeanFactory & ApplicationContext org.springframework.beans.factory.BeanFactory 是最基本的 Spring 容器接口 ...

  6. 【BZOJ】2442: [Usaco2011 Open]修剪草坪

    [算法]动态规划 [题解] 万物皆动规,每时每刻都要想着DP!特别是这种明显可以序列递推的题目. 一个简单的思路是f[i]表示前i个选择合法方案(第i个可选可不选)的最大效率 f[i]=max(f[i ...

  7. Mac git

    多次提交代码,与合并的工作量成反比. in terminal window git status:查看git的状态 git add -A: 把所有不再track里的文件加入进去/ git add -u ...

  8. kuangbin带你飞 后缀数组 题解

    2份模板 DC3 . 空间复杂度O3N 时间复杂度On #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb)) #define G(x) ((x) < ...

  9. Charles Android 抓包失败SSLHandshake: Received fatal alert: certificate_unknown

    前提: Android使用Charles抓取Https请求的报文时,Android和Charles都正确安装了证书之后出现抓包失败,报错SSLHandshake: Received fatal ale ...

  10. Ubuntu系统进程管理笔记

    前言 今天对前端服务器进行迁移,本来前端服务器就一台,都是放置前端静态文件的地方,应该是比较简单的.唯一的问题是由于Nginx需要给ie8浏览器个i同https访问支持,不得不对Nginx进行重新编译 ...