HDU - 5036 Explosion floyd(bitset优化) + 概率期望

题意:给出n个房间。每个房间上都有锁。每个房间内有一定数量的能开其他房间的钥匙,若当前手里的钥匙不能再打开新的房间,我们可以选择用炸弹炸开一个新的房间,给出每个房间中钥匙的数目和具体能开那个房间,求要打开所有房间,需要使用的炸弹数目。

思路:单独考虑每个点打开需要用炸弹的期望次数,那么所有点的期望之和就是答案。每个点 v 需要用炸弹的期望次数是 1/S, S是u(u->v连通)的数量,然后就变成求图中多少点能到达图中任意一个点了,这就是要求这个图的传递闭包了,普通的floyd显然会tle,新get的技巧是用bitset优化。至于期望为什么是1/S,因为对应能打开该房间的这S个房间里面必定要用一个炸弹砸开,而砸v的概率为1/S。

代码:

#include<bits/stdc++.h>
#define MAXN 1001
using namespace std;
int n;
bitset<MAXN> mp[MAXN];
double floyd()
{
	double ans = 0;
	int cnt = 0;
	for(int i = 1; i <= n; i++)
	for(int j = 1; j <= n; j++)
	if(mp[j][i]) mp[j] |= mp[i];
	for(int i = 1; i <= n; i++)
	{
		cnt = 0;
		for(int j = 1; j <= n; j++)
		if(mp[j][i]) cnt++;
		ans += 1.0 / cnt;
	}
	return ans;
}
int main()
{
	int T, k, u, kase = 1;
	cin >> T;
	while(T--)
	{
		scanf("%d", &n);
		for(int i = 1; i <= n; i++) mp[i].reset();
		for(int i = 1; i <= n; i++)
		{
			scanf("%d", &k);
			while(k--){
				scanf("%d", &u);
				mp[i][u] = 1;
			}
			mp[i][i] = 1;
		}
		printf("Case #%d: %.5lf\n", kase++, floyd());
	}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值