传送门:洛谷 [[AGC049A] Erasing Vertices](https://www.luogu.com.cn/problem/AT_agc049_a) | AtCoder A - Erasing Vertices

更佳的阅读体验:AGC049A 题解


简要题意:$n$ 个点的简单有向图。重复等概率随机选定一个还未删除的点,删除它和它能到达的点,直到图中没有任何未被删除的点。求期望进行多少次操作后会把图删完。

首先来考虑每个点被删掉的概率。

对于 $x$ 还未被删除时的任意一次操作,如果随到了 $x$,则 $x$ 被选中,如果随到了能到达 $x$ 的其它点,则 $x$ 不可能被选中,否则继续选点。由此过程可知,设 $f_x$ 为能到达 $x$ 的点数(包括 $x$ 本身),则 $x$ 被选中的概率为 $\dfrac{1}{f_x}$ 。

我们知道,期望是线性函数。因此,直接暴力计算出每个点的 $f_i$,答案即为 $\sum \limits_{i = 1}^{n} f_i$。

#include <iostream>
#include <bitset>
using namespace std;

const int N = 110;
int n, f[N];
char c;
bitset<N> g[N], vis;
double ans;

void dfs(int u) {
    if (vis[u]) return;
    ++f[u], vis.set(u);
    for (int i = 1; i <= n; ++i) if (g[u][i]) dfs(i);
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j) cin >> c, g[i].set(j, c == '1');
    for (int i = 1; i <= n; ++i) vis.reset(), dfs(i);
    for (int i = 1; i <= n; ++i) ans += 1.0 / f[i];
    cout.precision(12);
    cout << fixed << ans << '\n';
    return 0;
}
最后修改:2024 年 05 月 06 日
如果觉得我的文章对你有用,请随意赞赏