BZOJ 2730 HNOI2012 矿场搭建 Tarjan

题目大意:给定一个无向图,要求将一些点设为出口 要求图中删掉任意一个点后剩余的任意一个点都与至少一个出口相连 求最少建多少个出口以及建最少出口的方案数

首先看到割点就是Tarjan搞 但是怎么搞

首先假设我们把所有的点双都缩点 那么我们一定可以得到一棵树 然后我们就会发现

叶子节点(只含有一个割点的点双)必须建 因为叶子节点如果不建 一旦割点被爆就死翘了

非叶节点(含有两个或两个以上的割点的点双)不用建 因为即使一个割点被爆了也可以沿着另一个割点走到一个叶节点

还有一种情况就是整个联通块都是点双(即不含割点的点双) 这样我们讨论点双的大小

如果只有一个点 那么这个点必须建 数据没有卡这个的点所以我没写(其实是我忘写了 然后还过了)

如果有两个或两个以上的点 那么要建两个 一个被爆了还可以走另一个

方案数就是乘法原理的问题了 注意叶节点那里出口不能建在割点上

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 1010
using namespace std;
typedef long long ll;
struct abcd{
	int to,next;
}table[M];
int head[M],tot=1;
int n,m,cases,ans1;
long long ans2;
int dpt[M],low[M],cnt,belong[M],stack[M],top;
inline void Initialize()
{
	memset(head,0,sizeof head);
	memset(dpt,0,sizeof dpt);
	memset(belong,0,sizeof belong);
	tot=1;n=0;ans1=0;ans2=1;
}
void Add(int x,int y)
{
	table[++tot].to=y;
	table[tot].next=head[x];
	head[x]=tot;
}
void Tarjan(int x)
{
	int i;
	dpt[x]=low[x]=++cnt;
	for(i=head[x];i;i=table[i].next)
	{
		int y=table[i].to;
		if(dpt[y])
			low[x]=min(low[x],dpt[y]);
		else
		{
			Tarjan(y);
			low[x]=min(low[x],low[y]);
			if(low[y]>=dpt[x])
				belong[x]++;
		}
	}
}
void _Tarjan(int x)
{
	int i;
	dpt[x]=low[x]=++cnt;
	stack[++top]=x;
	for(i=head[x];i;i=table[i].next)
	{
		int y=table[i].to;
		if(dpt[y])
			low[x]=min(low[x],dpt[y]);
		else
		{
			_Tarjan(y);
			low[x]=min(low[x],low[y]);
			if(low[y]>=dpt[x])
			{
				int t,temp=0,size=0;
				do{
					t=stack[top--];
					if(belong[t]>=2)
						++temp;
					++size;
				}while(t!=x);
				stack[++top]=x;
				if(!temp)
					ans1+=2,ans2*=size*(size-1)/2;
				else if(temp==1)
					ans1++,ans2*=size-1;
			}
		}
	}
}
int main()
{

	//freopen("2730.in","r",stdin);

	int i,x,y;
	while(scanf("%d",&m),m)
	{
		Initialize();
		for(i=1;i<=m;i++)
		{
			scanf("%d%d",&x,&y);
			n=max(n,x);
			n=max(n,y);
			Add(x,y);
			Add(y,x);
		}
		for(i=1;i<=n;i++)
			if(!dpt[i])
				Tarjan(i);
			else
				belong[i]++;
		memset(dpt,0,sizeof dpt);
		for(i=1;i<=n;i++)
			if(!dpt[i])
				_Tarjan(i);
		cout<<"Case "<<++cases<<": ";
		cout<<ans1<<' '<<ans2<<endl;
	}
}
时间: 2024-10-28 23:39:01

BZOJ 2730 HNOI2012 矿场搭建 Tarjan的相关文章

bzoj 2730: [HNOI2012]矿场搭建

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

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

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

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

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

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

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

[HNOI2012]矿场搭建 题解

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

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

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

【BZOJ 2730】 [HNOI2012]矿场搭建

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

【bzoj2730】 HNOI2012—矿场搭建

http://www.lydsy.com/JudgeOnline/problem.php?id=2730 (题目链接) 题意 给出一张图,问如果删掉其中一个点,使得其他每个节点都有一个安全撤离的出口,最少需要设立多少个出口,有多少种方案. Solution 很明显,一张图至少要设立2个出口(一个点双连通分量),如果删掉不是割点的点,对答案不会有什么限制,考虑删掉的点是割点. 我们对割点以外的联通快进行染色,每一种颜色就表示在这些同样的颜色中的节点至少要设置一个出口,若一个节点被染成了多种颜色,那

[HNOI2012]矿场搭建

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