HDU - 5036

Problem Description
Everyone knows Matt enjoys playing games very much. Now, he is playing such a game. There are N rooms, each with one door. There are some keys(could be none) in each room corresponding to some doors among these N doors. Every key can open only one door. Matt has some bombs, each of which can destroy a door. He will uniformly choose a door that can not be opened with the keys in his hand to destroy when there are no doors that can be opened with keys in his hand. Now, he wants to ask you, what is the expected number of bombs he will use to open or destroy all the doors. Rooms are numbered from 1 to N.

Input
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.

Output
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.

Sample Input
2
3
1 2
1 3
1 1
3
0
0
0

Sample Output
Case #1: 1.00000
Case #2: 3.00000


首先要求出对于每个门,有多少扇门的打开会导致这扇门的打开。这就是一个传递闭包的过程。但是暴力floyd会TLE,所以我们用位运算优化即可,也就是用Bitset加速。

用p[i]表示能导致第i个房间被开打的房间,全部都排在第i个房间后面的概率,只有在这时,对于第i个房间就必须强行炸一次,于是其实答案就是(∑p[i])。p[i]怎么算呢?这个点排在整个全排列的前面,概率显然是1/k啦
所以总的期望就是先是∑(1/k[i])啦


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e3+10;
int n,ts;
bitset<N> bit[N];
inline void floyd(){
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(bit[j][i])	bit[j]|=bit[i];
}
inline void solve(){
	cin>>n;
	for(int i=1;i<=n;i++)	bit[i].reset();
	for(int i=1,k,x;i<=n;i++){
		bit[i][i]=1;	scanf("%d",&k);
		while(k--)	scanf("%d",&x),bit[x][i]=1;
	}
	floyd();	double res=0;
	for(int i=1;i<=n;i++)	res+=(1.0/bit[i].count());
	printf("Case #%d: %.5lf\n",++ts,res);
}
signed main(){
	int T;	cin>>T;
	for(int i=1;i<=T;i++)	solve();
	return 0;
}
发布了487 篇原创文章 · 获赞 241 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/104106414
hdu
今日推荐