P3225 [HNOI2012]矿场搭建

题目描述

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

请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。

输入输出格式

输入格式:

输入文件有若干组数据,每组数据的第一行是一个正整数 N(N<=500),表示工地的隧道数,接下来的 N 行每行是用空格隔开的两个整数 S 和 T,表示挖 S 与挖煤点 T 由隧道直接连接。输入数据以 0 结尾。

输出格式:

输入文件中有多少组数据,输出文件 output.txt 中就有多少行。每行对应一组输入数据的 结果。其中第 i 行以 Case i: 开始(注意大小写,Case 与 i 之间有空格,i 与:之间无空格,: 之后有空格),其后是用空格隔开的两个正整数,第一个正整数表示对于第 i 组输入数据至少需 要设置几个救援出口,第二个正整数表示对于第 i 组输入数据不同最少救援出口的设置方案总 数。输入数据保证答案小于 2^64。输出格式参照以下输入输出样例。


最开始想的是统计把所有割点割掉之后联通分量的块数,就没怎么想了10分,谁知道这题是个分类讨论。

我们讨论最初的每个联通分量。

  1. 当这个联通分量是个双联通分量,即没有割点的联通分量时。

    若这个联通分量大小是1,则一定出口++,方案不变。

    若这个联通分量大小大于1,则出口设2个(防止某个出口被爆),方案乘上\(C_n^2\),\(n\)为联通块大小。
  2. 当这个联通分量存在割点时。

    我们讨论分离出割点后它的每一个双联通分量。

    若它的一个双联通分量(整体)与一个割点相连,则出口++,方案乘上双联通分量大小。

    原因:当双联通分量中的点爆掉后,从割点跑(到另外的双联通分量);当割点爆掉后,从双联通分量中设的点跑。

    若它的一个双联通分量与至少两个割点相连,这个双联通分量不用设出口,因为不管是割点爆还是里面爆,都可以向另外的双联通分量跑。

    对于为什么跑向别的双联通分量后一定有出口,可以这么想,对于每一个 有很多个割点与双联通分量相连构成的 联通分量,至少存在两端是 与一个割点连接的双联通分量,这样的双联通分量是一定要设出口的。

code:

#include <cstdio>
#include <cstring>
#define ll long long
int min(int x,int y){return x<y?x:y;}
const int N=504;
struct Edge
{
int to,next;
}edge[N<<1];
int head[N],cnt=0;
void add(int u,int v)
{
edge[++cnt].next=head[u];edge[cnt].to=v;head[u]=cnt;
}
int dfn[N<<1],low[N<<1],vis[N<<1],used[N<<1],is[N<<1];
int m,n,k=0,time=0;
ll ans1,ans2,siz,cut;
void tarjan(int now,int fa)
{
int child=0;
dfn[now]=low[now]=++time;
for(int i=head[now];i;i=edge[i].next)
{
int v=edge[i].to;
if(!dfn[v])
{
tarjan(v,fa);
low[now]=min(low[now],low[v]);
if(low[v]>=dfn[now]&&now!=fa)
vis[now]=1;
if(now==fa) child++;
}
low[now]=min(low[now],dfn[v]);
}
if(fa==now&&child>1)
vis[now]=1;
}
void dfs(int now)
{
used[now]=1;
siz++;
for(int i=head[now];i;i=edge[i].next)
{
int v=edge[i].to;
if(!vis[v]&&!used[v]) dfs(v);
if(vis[v]&&!is[v]) cut++,is[v]=1;
}
}
void init()//记得待会检查全不全
{
memset(head,0,sizeof(head));
memset(used,0,sizeof(used));
memset(vis,0,sizeof(vis));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
cnt=0,n=0,time=0,ans1=0,ans2=1,cnt=0,k++;
}
int main()
{
scanf("%d",&m);
while(m)
{
init();
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
if(!used[u])
{
used[u]=1;
n++;
}
if(!used[v])
{
used[v]=1;
n++;
}
}
for(int i=1;i<=n;i++)
if(!dfn[i]&&!vis[i])
tarjan(i,i);
memset(used,0,sizeof(used));
for(int i=1;i<=n;i++)
if(!vis[i]&&!used[i])
{
siz=0;
cut=0;
memset(is,0,sizeof(is));
dfs(i);
if(!cut)
{
if(siz!=1)
{
ans1+=2;
ans2*=siz*(siz-1)/2;
}
else
ans1++;
}
else if(cut==1)
{
ans1++;
ans2*=siz;
}
}
printf("Case %d: %lld %lld\n",k,ans1,ans2);
scanf("%d",&m);
}
}

2018.6.8

洛谷 P3225 [HNOI2012]矿场搭建 解题报告的更多相关文章

  1. 洛谷——P3225 [HNOI2012]矿场搭建

    P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...

  2. 洛谷P3225 HNOI2012 矿场搭建

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

  3. 洛谷 P3225 [HNOI2012]矿场搭建

    传送门 题目大意:建设几个出口,使得图上无论哪个点被破坏,都可以与出口联通. 题解:tarjian求割点 首先出口不能建在割点上,找出割点,图就被分成了几个联通块. 每个联通块,建出口.如果割点数为0 ...

  4. 洛谷—— P3225 [HNOI2012]矿场搭建

    https://www.luogu.org/problem/show?pid=3225 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有 ...

  5. BZOJ2730或洛谷3225 [HNOI2012]矿场搭建

    BZOJ原题链接 洛谷原题链接 显然在一个点双连通分量里,无论是哪一个挖煤点倒塌,其余挖煤点就可以互相到达,而对于一个点双连通分量来说,与外界的联系全看割点,所以我们先用\(tarjan\)求出点双连 ...

  6. 洛谷_Cx的故事_解题报告_第四题70

    1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h>   struct node {     long x,y,c; ...

  7. 洛谷 P2317 [HNOI2005]星际贸易 解题报告

    P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...

  8. 洛谷 P3802 小魔女帕琪 解题报告

    P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...

  9. 洛谷 P2606 [ZJOI2010]排列计数 解题报告

    P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...

随机推荐

  1. 生成32位UUID及生成指定个数的UUID

    参考地址:https://blog.csdn.net/xinghuo0007/article/details/72868799 UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯 ...

  2. Luogu P3388 【模板】割点(割顶)

    一道求割点的板子题.还是采用经典的Tarjan算法. 首先大致和Tarjan求强连通分量相似,都是用\(dfn_x\)表示访问到\(x\)的时间(时间戳),\(low_x\)表示通过\(x\)回边能走 ...

  3. Notepad++中的颜色属性设置大全

    Indent guideline style  缩进参考线的颜色Brace highlight style 鼠标指针在框架左右时框架的颜色(如css中{}   js中的())Bad brace col ...

  4. Spring Boot 2.0 版的开源项目云收藏来了!

    给大家聊一聊云收藏从 Spring Boot 1.0 升级到 2.0 所踩的坑 先给大家晒一下云收藏的几个数据,作为一个 Spring Boot 的开源项目(https://github.com/cl ...

  5. C/C++中连接函数strcat的应用(简单讲解)

    有位学弟问到我如何将两个字符连接起来,想想java/python里面可以直接用+连接起来,可是C/C++里面有没有这么方便的做法呢? 答案是有的,在C语言的string.h库中有个神奇的函数叫做str ...

  6. 利用Tarjan算法解决(LCA)二叉搜索树的最近公共祖先问题——数据结构

    相关知识:(来自百度百科)  LCA(Least Common Ancestors) 即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. 例如: 1和7的最近公共祖先为5: 1和5的 ...

  7. Reading Task 2 —— by12061154Joy

    关于Silver Bullet: Brooks在“No Silver Bullet”主张并断言在未来的十年之内(从1986年文章发表后开始计算),不会有任何单一的软件工程上的突破,能够让程序设计的生产 ...

  8. “数学口袋精灵”第二个Sprint计划(第六~八天)

    “数学口袋精灵”第二个Sprint计划----第六天~第八天进度 任务分配: 冯美欣:欢迎界面的背景音乐完善 吴舒婷:游戏界面的动作条,选择答案后的音效 林欢雯:代码算法设计 第六天: 进度: 冯美欣 ...

  9. varnish页面缓存服务

    varnish页面缓存服务 https://www.cnblogs.com/L-dongf/p/9310144.html http://blog.51cto.com/xinzong/1782669 阅 ...

  10. shell脚本--制作自己的服务脚本

    首先注意一下,我用的环境是centos6.5,中间有一些操作和在Ubuntu上有一些地方的操作是不同的, 编写脚本 首先看一个实例:假设有一个test的服务,可以通过命令对test进行启动.关闭或者重 ...