【题目大意】

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

【思路】

可以得出这样的结论:

(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. [hdu 4348]区间修改区间查询可持久化线段树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4348 一开始把lazy标记给push_down了,后来发现这样会让持久化变乱,然后想到不用push_d ...

  2. 1040: [ZJOI2008]骑士~基环外向树dp

    Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中 ...

  3. ubunut14.04 mentohust配置

      1.设置网卡eth0的IP地址和子网掩码 sudo ifconfig eth0 10.162.32.94 netmask 255.0.0.0 将IP地址改为:10.162.32.94,子网掩码改为 ...

  4. codeforces 111D

    题目链接 D. Petya and Coloring time limit per test 5 seconds memory limit per test 256 megabytes input s ...

  5. bzoj1574 [Usaco2009 Jan]地震损坏Damage

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1574 [题解] 贪心把report的点的旁边所有点破坏即可. # include <s ...

  6. mongoDB的简单使用

    1.客户端连接: ./mongo 2.数据库 一个mongodb中可以建立多个数据库. MongoDB的默认数据库为"db",该数据库存储在data目录中. MongoDB的单个实 ...

  7. module加载过程初步分析[更新中]【转】

    转自:http://blog.chinaunix.net/uid-1817735-id-2837068.html 分析这个过程可以有助于我们认识在加载模块时出现的问题大抵在哪里了. 直接从sys_in ...

  8. 查询ubuntu系统版本相关信息

    查询ubuntu系统版本相关信息 sky@sky-virtual-machine:~$ cat /etc/issueUbuntu 12.04.5 LTS \n \l proc目录下记录的当前系统运行的 ...

  9. 在react项目中使用ECharts

    这里我们要在自己搭建的react项目中使用ECharts,我们可以在ECharts官网上看到有一种方式是在 webpack 中使用 ECharts,我们需要的就是这种方法. 我们在使用ECharts之 ...

  10. celery-分布式任务队列-原理

    # 转自:https://www.cnblogs.com/forward-wang/p/5970806.html 在学习Celery之前,我先简单的去了解了一下什么是生产者消费者模式. 生产者消费者模 ...