【bzoj2730】 HNOI2012—矿场搭建

http://www.lydsy.com/JudgeOnline/problem.php?id=2730 (题目链接)

题意

  给出一张图,问如果删掉其中一个点,使得其他每个节点都有一个安全撤离的出口,最少需要设立多少个出口,有多少种方案。

Solution

  很明显,一张图至少要设立2个出口(一个点双连通分量),如果删掉不是割点的点,对答案不会有什么限制,考虑删掉的点是割点。

  我们对割点以外的联通快进行染色,每一种颜色就表示在这些同样的颜色中的节点至少要设置一个出口,若一个节点被染成了多种颜色,那么表明在此处设立出口不是最优的。

细节

  十个Tarjan五个错。。注意判断割点的条件,当判断搜索树根是不是割点时,有点小麻烦。

代码

// bzoj2730
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

const int maxn=1010;
struct edge {int to,next;}e[maxn<<1];
int low[maxn],dfn[maxn],head[maxn],cut[maxn],vis[maxn],id[maxn],sum[maxn];
int cnt,ind,m,n;

void Init() {
	cnt=ind=n=0;
	memset(head,0,sizeof(head));
	memset(vis,0,sizeof(vis));
	memset(cut,0,sizeof(cut));
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	memset(sum,0,sizeof(sum));
	memset(id,0,sizeof(id));
}
void link(int u,int v) {
	e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
	e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;
}
void Tarjan(int x,int fa,int rt) {
	int tot=0;
	dfn[x]=low[x]=++ind;
	for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa) {
			if (!dfn[e[i].to]) {
				Tarjan(e[i].to,x,rt);
				low[x]=min(low[x],low[e[i].to]);
				if (low[e[i].to]>=dfn[x] && x!=rt) cut[x]=1;   //important
				else if (x==rt) tot++;
			}
			else low[x]=min(low[x],dfn[e[i].to]);
		}
	if (tot>1) cut[x]=1;   //important
}
void dfs(int x,int col) {
	vis[x]=cnt;
	if (!id[x]) id[x]=col;
	else id[x]=-1;
	for (int i=head[x];i;i=e[i].next)
		if (vis[e[i].to]!=cnt && !cut[e[i].to]) dfs(e[i].to,col);
}
int main() {
	int T=0;
	while (1) {
		scanf("%d",&m);
		if (m==0) break;
		printf("Case %d: ",++T);
		Init();
		for (int u,v,i=1;i<=m;i++) {
			scanf("%d%d",&u,&v);
			link(u,v);n=max(n,max(u,v));
		}
		for (int i=1;i<=n;i++) if (!dfn[i]) Tarjan(i,0,i);
		cnt=0;int col=0;
		for (int i=1;i<=n;i++) if (cut[i]) {
				cnt++;
				for (int j=head[i];j;j=e[j].next)
					if (vis[e[j].to]!=cnt && !cut[e[j].to]) dfs(e[j].to,++col);
			}
		for (int i=1;i<=n;i++) if (id[i]!=-1) sum[id[i]]++;
		int tot=0;LL ans=1;
		for (int i=1;i<=col;i++) if (sum[i]) tot++,ans=ans*sum[i];
		if (!tot) printf("2 %d\n",n*(n-1)/2);
		else printf("%d %lld\n",tot,ans);
	}
	return 0;
}

  

时间: 2024-08-13 19:45:44

【bzoj2730】 HNOI2012—矿场搭建的相关文章

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

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2730 分析: 如果坍塌的点不是割点,那没什么影响,主要考虑坍塌的点是割点的情况. 显然我们可以先求出所有割点把整个图分成若干个连通块 如果一个联通块只与一个割点相连,说明我们必须在这个连通块中选一个点作为出口 如果一个联通块与两个以上的割点相连,那么就可以不在这些点取一个作为出口 方案数就是要取点的联通块的点的个数的乘积 注意没有割点的情况要放2个点

bzoj2730: [HNOI2012]矿场搭建

Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数. Input 输入文件有若干组数据,每组数据的第一行是一个正整数 N(N≤500),表示工地的隧道数,接下来的 N 行每行是用空格隔开的两个整数 S 和 T

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

Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数. Sulotion 坍塌的不是割顶并不影响,建在割顶也没有意义(拆割顶) 考虑每一个双连通分量,如果只连一个割顶必须内部建一个(随便选一个),连两个以上可以

BZOJ 2730:[HNOI2012]矿场搭建(割点+连通块)

[HNOI2012]矿场搭建 Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数.Input 输入文件有若干组数据,每组数据的第一行是一个正整数 N(N≤500),表示工地的隧道数,接下来的 N 行每行是用空

[HNOI2012]矿场搭建 题解

[HNOI2012]矿场搭建 时间限制: 1 Sec  内存限制: 128 MB 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数. 输入 输入文件有若干组数据,每组数据的第一行是一个正整数 N(N≤500),表示工地的

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

P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口. 请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数. 输入输出格式 输入格式: 输入文件有若干组数据,每组数据的第一行是一个正整数 N(N<=500),表示工地的隧道数,接下来的

【BZOJ-2730】矿场搭建 Tarjan 双连通分量

2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1602  Solved: 751[Submit][Status][Discuss] Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用

cogs——1348. [HNOI2012]矿场搭建

1348. [HNOI2012]矿场搭建 ★★★   输入文件:bzoj_2730.in   输出文件:bzoj_2730.out   简单对比时间限制:1 s   内存限制:128 MB [题目描述] 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少

[HNOI2012]矿场搭建

明明是Acm World Finals 2011的原题,把数据范围改小了就放出来了?!这样不好,, 昨天讲完双连通分量今天A一道点双的题. Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数. Input 输