【题目大意】

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

【思路】

可以得出这样的结论:

(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. [codeforces/gym/100431/E]KMP关于border的理解

    题目链接:http://codeforces.com/gym/100431/ 考虑到对于一个串β,能cover它的最短的α必然是它的border的某个前缀,或者是这个β本身. 所谓border,就是n ...

  2. Tumblr:150亿月浏览量背后的架构挑战

    Tumblr:150亿月浏览量背后的架构挑战 2013/04/08 · IT技术, 开发 · 9.9K 阅读 · HBase, Tumblr, 架构 英文原文:High Scalability,编译: ...

  3. docker公司测试环境搭建总结

    1.防火墙转发规则: [root@docker ~]# firewall-cmd --list-allpublic (active) target: default icmp-block-invers ...

  4. Bash 实例,第二部分

    我们先看一下处理命令行自变量的简单技巧,然后再看看 bash 基本编程结构. 接收自变量 在 介绍性文章 中的样本程序中,我们使用环境变量 "$1" 来引用第一个命令行自变量.类似 ...

  5. (转)用python实现抓取网页、模拟登陆

    涉及一系列内容,部分已在前面转载,仍转自crifan: http://www.crifan.com/how_to_use_some_language_python_csharp_to_implemen ...

  6. IE9,IE10 CSS因Mime类型不匹配而被忽略问题 (转)

    写页面的时候在chrome,fireforks等页面上显示正常,但是换成IE9,IE10之后就完全没有样式了,报错信息是CSS 因 Mime 类型不匹配而被忽略,下面与大家分享下这个问题的相关的回答 ...

  7. Matlab xpC启动盘

    要点: 1.target PC的网卡支持类型有限: 2.网上所列教程未必适用于本地,仅以两图表示: a,带有图形界面时容易出错: b,启动选项为Removable Device:

  8. 【BZOJ】5028: 小Z的加油店

    [算法]数学+线段树/树状数组 [题解] 首先三个操作可以理解为更相减损术或者辗转相除法(待证明),所以就是求区间gcd. 这题的问题在线段树维护gcd只能支持修改成一个数,不支持加一个数. 套路:g ...

  9. usaco 月赛 2005 january watchcow

    2013-09-18 08:13 //By BLADEVIL var n, m :longint; pre, other :..] of longint; last :..] of longint; ...

  10. 使用腾讯云 GPU 学习深度学习系列之二:Tensorflow 简明原理【转】

    转自:https://www.qcloud.com/community/article/598765?fromSource=gwzcw.117333.117333.117333 这是<使用腾讯云 ...