题目描述
有n个房间,每个房间中都放有一些钥匙,每个钥匙都能打开且仅能打开一个房间的门。对于无法直接用钥匙打开的门可以用炸弹炸开,求打开所有门使用炸弹次数的期望。
输入输出格式
The first line of the input contains an integer T, denoting the number of testcases. Then T test cases follow.
In the first line of each test case, there is an integer N (N<=1000) indicating the number of rooms.
The following N lines corresponde to the rooms from 1 to N. Each line begins with an integer k (0<=k<=N) indicating the number of keys behind the door. Then k integers follow corresponding to the rooms these keys can open.
For each test case, output one line “Case #x: y”, where x is the case number (starting from 1), y is the answer which should be rounded to 5 decimal places.
对于开每个箱子之后能开出的所有箱子的集合用bitset预处理
假设每个箱子能通过开k个箱子开出来,那么每次能通过炸开某个箱子来打开这个箱子的概率就是
kn
,也就相当于需要使用
nk
次炸弹才能打开这个箱子,将所有次数加在一起后除以n即为期望。
#include<bits/stdc++.h>
#define fer(i,j,n) for(int i=j;i<=n;i++)
#define far(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<int,int>
const int maxn=1010;
const int INF=1e9+7;
using namespace std;
/*----------------------------------------------------------------------------*/
inline ll read()
{
char ls;ll x=0,sng=1;
for(;ls<'0'||ls>'9';ls=getchar())if(ls=='-')sng=-1;
for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
return x*sng;
}
/*----------------------------------------------------------------------------*/
int n;
bitset<maxn> f[maxn];
int main()
{
int T=read();
fer(t,1,T)
{
n=read();
fer(i,1,n)
{
f[i].reset();
f[i][i]=1;
}
fer(i,1,n)
{
int k=read();
fer(j,1,k)
{
int x=read();
f[i][x]=1;
}
}
fer(i,1,n)
fer(j,1,n)
if(f[j][i])
f[j]|=f[i];
double ans=0;
fer(i,1,n)
{
int cnt=0;
fer(j,1,n)if(f[j][i])cnt++;
ans+=(double)1/cnt;
}
printf("Case #%d: %.5lf\n",t,ans);
}
}