HDU 5036 Explosion
Posted mjtcn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5036 Explosion相关的知识,希望对你有一定的参考价值。
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,求传递闭包。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8 #include<vector> 9 #include<queue> 10 #include<map> 11 #include<bitset> 12 #define fi(s) freopen(s,"r",stdin); 13 #define fo(s) freopen(s,"w",stdout); 14 using namespace std; 15 typedef long long LL; 16 17 inline int read() { 18 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1; 19 for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘;return x*f; 20 } 21 22 const int N = 1001; 23 bitset<N> e[N]; 24 25 void solve() { 26 int n = read(); 27 for (int i=1; i<=n; ++i) 28 e[i].reset(), e[i].set(i); 29 for (int i=1; i<=n; ++i) 30 for (int x = read(), y; x --; ) y = read(), e[i].set(y); 31 for (int i=1; i<=n; ++i) 32 for (int j=1; j<=n; ++j) 33 if (e[j][i]) e[j] |= e[i]; 34 double sum = 0, cnt = 0; 35 for (int i=1; i<=n; ++i) { 36 cnt = 0; 37 for (int j=1; j<=n; ++j) 38 if (e[j][i]) cnt ++; 39 sum += 1.0 / cnt; 40 } 41 printf("%.5lf ",sum); 42 } 43 44 int main() { 45 int T = read(); 46 for (int i=1; i<=T; ++i) { 47 printf("Case #%d: ",i); solve(); 48 } 49 return 0; 50 }
以上是关于HDU 5036 Explosion的主要内容,如果未能解决你的问题,请参考以下文章
hdu 5036 Explosion bitset优化floyd