您的位置:首页 > 其它

HDU 5036 Explosion

2018-10-09 20:12 316 查看

Explosion

http://acm.hdu.edu.cn/showproblem.php?pid=5036

题意:

  n扇门,每扇门里面有一些钥匙,一个钥匙可以打开一扇门,如果没有钥匙可以打开门,那么随机选择一扇门炸开。求期望炸多少次。

分析:

  bitset优化Floyd传递闭包。

  根据期望的线性性,求出每扇门炸的概率,乘以1就是答案。将原问题转化为一张有向图,x->y,说明x有y的钥匙。如果有s扇门可以到达x(不一定连向,联通即可,说明到了这个点,然后根据这个点的钥匙,到下一个点,最后直到x),那么炸x的概率就是1/s。x也在这s个里面,表示可以直接炸x。然后用bitset优化Floyd,求传递闭包。

 

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#include<bitset>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL;

inline int read() {
int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 1001;
bitset<N> e
;

void solve() {
int n = read();
for (int i=1; i<=n; ++i)
e[i].reset(), e[i].set(i);
for (int i=1; i<=n; ++i)
for (int x = read(), y; x --; ) y = read(), e[i].set(y);
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j)
if (e[j][i]) e[j] |= e[i];
double sum = 0, cnt = 0;
for (int i=1; i<=n; ++i) {
cnt = 0;
for (int j=1; j<=n; ++j)
if (e[j][i]) cnt ++;
sum += 1.0 / cnt;
}
printf("%.5lf\n",sum);
}

int main() {
int T = read();
for (int i=1; i<=T; ++i) {
printf("Case #%d: ",i); solve();
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: