洛谷——P3225 [HNOI2012]矿场搭建
P3225 [HNOI2012]矿场搭建
题目描述
煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。
请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。
输入输出格式
输入格式:
输入文件有若干组数据,每组数据的第一行是一个正整数 N(N<=500),表示工地的隧道数,接下来的 N 行每行是用空格隔开的两个整数 S 和 T,表示挖 S 与挖煤点 T 由隧道直接连接。输入数据以 0 结尾。
输出格式:
输入文件中有多少组数据,输出文件 output.txt 中就有多少行。每行对应一组输入数据的 结果。其中第 i 行以 Case i: 开始(注意大小写,Case 与 i 之间有空格,i 与:之间无空格,: 之后有空格),其后是用空格隔开的两个正整数,第一个正整数表示对于第 i 组输入数据至少需 要设置几个救援出口,第二个正整数表示对于第 i 组输入数据不同最少救援出口的设置方案总 数。输入数据保证答案小于 2^64。输出格式参照以下输入输出样例。
输入输出样例
9 1 3 4 1 3 5 1 2 2 6 1 5 6 3 1 6 3 2 6 1 2 1 3 2 4 2 5 3 6 3 7 0
Case 1: 2 4 Case 2: 4 1
说明
Case 1 的四组解分别是(2,4),(3,4),(4,5),(4,6);
Case 2 的一组解为(4,5,6,7)。
分情况讨论:
很显然是要求割点嘛、、、(分类上写着、、、)
好吧,求完割点以后干什么??
我一直认为是先求出割点,然后将割点全部炸掉(屏蔽)后求出每个联通块的点的个数,然后在用乘法原理来做。
结果发现全wa!!!(ORZ)
据说这道题要分类讨论、、、、
①若一个双联通中没有割点,那么最少需要两个出口(炸了一个去另一个)
②若一个双联通能连到一个割点,那么最少需要在双联通中设置一个出口,炸了割点还能逃生、
③若一个双联通能连到多余一个割点,那么不管怎么炸,都能从没炸的割点跑到别的分量里
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 510
using namespace std;
long long ans2;
bool vis[N],cut_point[N];
int n,m,x,y,s,tot,tim,cnt,cut,sum,ans1;
int dfn[N],low[N],head[N],belong[N];
int read()
{
,f=; char ch=getchar();
; ch=getchar();}
+ch-'; ch=getchar();}
return x*f;
}
struct Edge
{
int from,to,next;
}edge[N<<];
int add(int x,int y)
{
tot++;
edge[tot].to=y;
edge[tot].next=head[x];
head[x]=tot;
}
int begin()
{
memset(vis,,sizeof(vis));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(edge,,sizeof(edge));
memset(head,,sizeof(head));
memset(belong,,sizeof(belong));
memset(cut_point,,sizeof(cut_point));
n=,tot=,ans1=,ans2=,tim=,sum=;
}
int tarjan(int now,int pre)
{
dfn[now]=low[now]=++tim;
; bool boo=false;
for(int i=head[now];i;i=edge[i].next)
{
int t=edge[i].to;
^i)==pre) continue;
if(!dfn[t])
{
tt++;tarjan(t,i);
low[now]=min(low[now],low[t]);
if(dfn[now]<=low[t]) boo=true;
}
else low[now]=min(low[now],dfn[t]);
}
) {) cut_point[now]=true;}
else if(boo) cut_point[now]=true;
}
int dfs(int x)
{
s++;
vis[x]=true;
belong[x]=sum;
for(int i=head[x];i;i=edge[i].next)
{
int t=edge[i].to;
if(cut_point[t]&&belong[t]!=sum) cut++,belong[t]=sum;
if(!vis[t]&&!cut_point[t]) dfs(t);
}
}
int main()
{
)
{
m=read();) break;
begin();
;i<=m;i++)
{
x=read(),y=read();
add(x,y),add(y,x);
n=max(max(x,y),n);
}
;i<=n;i++)
);
;i<=n;i++)
{
if(vis[i]||cut_point[i]) continue;
s=,cut=;
sum++;dfs(i);
,ans2*=()>>);
) ans1++,ans2*=(long long)s;
}
printf("Case %d: %d %lld\n",++cnt,ans1,ans2);
}
;
}
傻不拉几的只考虑一种情况还调试半天、、、、结果全wa
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 11000
using namespace std;
bool vis[N],cut_point[N];
int n,m,tot,tim,sum,cnt,top,ans1,ans2;
int x[N],y[N],dfn[N],low[N],ans[N],head[N],stack[N],belong[N];
int read()
{
,f=; char ch=getchar();
; ch=getchar();}
+ch-'; ch=getchar();}
return x*f;
}
struct Edge
{
int from,to,next;
}edge[N];
int add(int x,int y)
{
tot++;
edge[tot].to=y;
edge[tot].next=head[x];
head[x]=tot;
}
int tarjan(int x,int pre)
{
; bool boo;
dfn[x]=low[x]=++tim;
vis[x]=true;
for(int i=head[x];i;i=edge[i].next)
{
int t=edge[i].to;
^i)==pre) continue;
if(!vis[t])
{
s++;tarjan(t,i);
low[x]=min(low[t],low[x]);
if(low[t]>=dfn[x]) boo=true;
}
else low[x]=min(low[x],dfn[t]);
}
) cut_point[x]=true;}
else {if(boo) cut_point[x]=true;}
}
int tarjan1(int now)
{
dfn[now]=low[now]=++tim;
stack[++top]=now;vis[now]=true;
for(int i=head[now];i;i=edge[i].next)
{
int t=edge[i].to;
if(vis[t]) low[now]=min(low[now],dfn[t]);
else if(!dfn[t]) tarjan1(t),low[now]=min(low[now],low[t]);
}
if(dfn[now]==low[now])
{
sum++; belong[now]=sum;ans[sum]++;
for(;stack[top]!=now;top--)
belong[stack[top]]=sum,vis[stack[top]]=false,ans[sum]++;
vis[now]=false; top--;
}
}
int begin()
{
tot=,tim=,sum=,ans2=;
memset(ans,,sizeof(ans));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(vis,,sizeof(vis));
memset(head,,sizeof(head));
memset(belong,,sizeof(belong));
}
int main()
{
)
{
m=read();) break;
begin();cnt++,tot=;
memset(cut_point,,sizeof(cut_point));
;i<=m;i++)
x[i]=read(),y[i]=read(),add(x[i],y[i]),add(y[i],x[i]);
tarjan(,); begin();
;i<=m;i++)
{
n=max(max(x[i],y[i]),n);
if(cut_point[x[i]]||cut_point[y[i]]) continue;
add(x[i],y[i]),add(y[i],x[i]);
}
;i<=n;i++)
if(!dfn[i]&&!cut_point[i]) tarjan1(i);
ans1=sum;
;i<=sum;i++)
ans2*=ans[i];
printf("Case %d: %d %d\n",cnt,ans1,ans2);
}
;
}
洛谷——P3225 [HNOI2012]矿场搭建的更多相关文章
- 洛谷 P3225 [HNOI2012]矿场搭建 解题报告
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- 洛谷P3225 HNOI2012 矿场搭建
题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之 ...
- 洛谷 P3225 [HNOI2012]矿场搭建
传送门 题目大意:建设几个出口,使得图上无论哪个点被破坏,都可以与出口联通. 题解:tarjian求割点 首先出口不能建在割点上,找出割点,图就被分成了几个联通块. 每个联通块,建出口.如果割点数为0 ...
- 洛谷—— P3225 [HNOI2012]矿场搭建
https://www.luogu.org/problem/show?pid=3225 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有 ...
- BZOJ2730或洛谷3225 [HNOI2012]矿场搭建
BZOJ原题链接 洛谷原题链接 显然在一个点双连通分量里,无论是哪一个挖煤点倒塌,其余挖煤点就可以互相到达,而对于一个点双连通分量来说,与外界的联系全看割点,所以我们先用\(tarjan\)求出点双连 ...
- P3225 [HNOI2012]矿场搭建 割点 tarjan 双联通分量
https://www.luogu.org/problemnew/show/P3225 题意 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条 ...
- P3225 [HNOI2012]矿场搭建 题解
这道题挺难的,可以加深对割点的理解,还有,排列组合好重要了,分连通块,然后乘法原理(加法原理计数什么的) 传送门 https://www.luogu.org/problem/P3225 省选oi题 ...
- P3225 [HNOI2012]矿场搭建
传送门 对于一个点双联通分量,如果它连接了两个或更多割点 那么不论哪个点GG都有至少一条路通到其他的点双联通分量,所以我们不用考虑 如果它只连接一个割点,如果这个割点GG,那整个块也一起GG,所以要再 ...
- [Luogu] P3225 [HNOI2012]矿场搭建
题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之 ...
随机推荐
- array_keys
<?php$array = array(0 => 100, "color" => "red");print_r(array_keys($arr ...
- es5/6数组遍历以及常用的一些方法
数组的遍历方法 1...for(var i=0;i<arr.length;i++){ } ---------------------------------------------------- ...
- 固定table表头
<style> #box{ height:214px; width:500px; overflow-y:auto;/** 必须,否则当表格数据过多时,不会产生滚动条,而是自动延长该div的 ...
- LibreOJ #101. 最大流
题目描述 这是一道模板题. 给定 n nn 个点,m mm 条边,给定每条边的容量,求从点 s ss 到点 t tt 的最大流. 输入格式 第一行四个整数 n nn.m mm.s ss.t tt.接下 ...
- 中间件及tomcat的内存溢出调优
主要是这三个选项的调整需要根据主机的内存配置 以及业务量的使用情况调节 -Xmx4g -Xms4g -Xmn2g xmx 与xms一般设置为一样 xmn大致设置为xmx xms的三分之一 可以使用 ...
- 插入insert几种用法
1.insert ignore into 当插入数据时,如出现错误时,如重复数据,将不返回错误,只以警告形式返回.所以使用ignore请确保语句本身没有问题,否则也会被忽略掉.例如: INSERT I ...
- linux_2
mac和linux上默认安装着SSH客户端,Windows上需要自己安装个软件. Windows下SSH客户端的安装:建议从官方网站下载正式程序安装(免费) Putty:https://www.chi ...
- vue中状态管理vuex的使用分享
一.main.js中引入 store import store from './store' window.HMO_APP = new Vue({ router, store, render: h = ...
- Chrome浏览器商店安装的插件保存到本地
Chrome自67版本开始,不能从第三方下载插件拖动安装,要么就是以前的方法安装修改为zip格式,会有报错(报错如下图),强迫症肯定忍不了报错的:按照网上说法,是第三方插件的压缩算法和Chrome商店 ...
- ajax 请求json数据中json对象的构造获取问题
前端的界面中,我想通过ajax来调用写好的json数据,并调用add(data)方法进行解析,请求如下: json数据如下: { “type”:"qqq", "lat&q ...