具体见代码注释:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bitset>
#define MAX 1007
using namespace std;
bitset<MAX> a[MAX];
int t,n,m,temp;
double ans ;
int main ( )
{
scanf ( "%d" , &t );
int c = 1;
while ( t-- )
{
ans = 0.0;
scanf ( "%d" , &n );
for ( int i = 0 ; i < n ; i++ )
{
a[i].reset();
a[i].set ( i );
}
for ( int i = 0 ; i < n ; i++ )
{
scanf ( "%d" , &m );
while ( m-- )
{
scanf ( "%d" , &temp );
a[i].set ( temp-1 );
}
}
//类似于求最短路的思想,将a[i]更新为所有可以到达i的点均为1的二进制集合
for ( int i = 0 ; i < n ; i++ )
for ( int j = 0 ; j < n ; j++ )
if ( a[j][i] )
a[j] |= a[i];
//因为在所有能够导致i打开的的方法就是炸掉任意一个可以到达i的点或者i本身,所以炸掉i的概率是1/sum(集合中i为1的个数)
for ( int i = 0 ; i < n ; i++ )
{
temp = 0;
for ( int j = 0 ; j < n ; j++ )
temp += a[j][i];
ans += 1.0/temp;
}
printf ( "Case #%d: " , c++ );
printf ( "%.5lf\n" , ans );
}
}