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\n",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 }

猜你喜欢

转载自www.cnblogs.com/mjtcn/p/9762519.html
hdu
今日推荐