题目链接:点我啊╭(╯^╰)╮
题目大意:
给一张有向图
初始时所有点都是白色的
每次随机选择一个点,将其能够到达的点全部染黑(包括它自己)
问染黑所有点的期望步数
n ≤ 1000 n≤1000 n≤1000
解题思路:
对于某一个点 x x x
能够到达点 x x x 的点有 G x Gx Gx 个(包括点x本身)
那么可以理解为:直接选取这个点的概率为 1 G x {1}\over{Gx} Gx1
则这个点对答案贡献期望是 1 G x {1}\over{Gx} Gx1
则求出每个点的期望后,根据期望的线性性,最后算出整体期望 ∑ 1 G x \sum{{1}\over{Gx}} ∑Gx1
要求出每个点的 ∣ G x ∣ ∣Gx∣ ∣Gx∣,可以用 b i t s e t bitset bitset 优化计算传递闭包
时间复杂度: O n 3 32 O{n^3}\over{32} 32On3
代码思路:
用 b i t s e t bitset bitset 来优化 f l o y e d floyed floyed
核心: b i t s e t bitset bitset 还是妙
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const ll mod = 1e9 + 7;
const int maxn = 3e5 + 10;
bitset <1010> a[1010];
int T, n, k, t, cas;
void floyed(){
for(rint i=1; i<=n; i++)
for(rint j=1; j<=n; j++)
if(a[j].test(i)) a[j] |= a[i];
}
int main() {
scanf("%d", &T);
while(T--){
scanf("%d", &n);
for(int i=1; i<=n; i++) a[i].reset();
for(int i=1; i<=n; i++){
scanf("%d", &k);
a[i].set(i);
while(k--){
scanf("%d", &t);
a[t].set(i);
}
}
floyed();
double ans = 0;
for(int i=1; i<=n; i++)
ans += 1.0 / a[i].count();
printf("Case #%d: %.5f\n", ++cas, ans);
}
}