1.hdu5036 Explosion
题意:一个有向图,每次随机选择一点遍历所有可达的点,直到无点可走时,再随机选择一点重复上述操作,问可以遍历图中所有的点的选择的起点数量的期望值。
注意题中的一个重要性质:当选择点u后,u可达的点不能再选
如果采用全期望公式,先计算出选择每个点的概率值pi,那么求和后即为总点数期望。
pi可通过上述性质来求。先求出可以到达u的点集数量x,那么选择u的概率一定为1/x。求和即为答案。
此题需要用bitset优化O(n^3)算法。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N maxn
#define PII pair<int,int>
#include<map>
#include<vector>
#define MP make_pair
#include<map>
#include<bitset>
#define ll int
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 1000+10;
int t,n;
bitset<maxn> e[maxn];
double ans;
int main(){
//freopen("a.txt","r",stdin);
int cas=0;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++) e[i].reset();
for(int i=1;i<=n;i++){
int k,x;
scanf("%d",&k);
while(k--){
scanf("%d",&x);
e[i][x]=1;
}
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
if(e[i][k]) e[i]|=e[k];
ans=0.0;
for(int i=1;i<=n;i++){
int cnt=1;
for(int j=1;j<=n;j++){
if(j!=i&&e[j][i]) cnt++;
}
ans=(ans+1.0/(cnt*1.0));
}
printf("Case #%d: %.5lf\n",++cas,ans);
}
return 0;
}