洛谷 P4819 杀人游戏
洛谷 P4819 杀人游戏
题意
有
每个人都有可能是杀手,并且概率相等。
你可以询问若干人。
若询问的人是杀手,你会被干掉。
若询问的人是平民,你会知道他认识的所有人的身份。
给出一张有向图表示这
求出你活着知道杀手是谁的概率。
思路
先将原图强连通分量缩点,每个点内的人都互相认识。
形成一张 DAG 后,我们只需要问那些入度为
问了他们之后,他们后面的点的身份都已知道,不会再有被杀死的风险。
所以概率为
但这还不全对。
如果存在一个点大小为
因为如果存在这样的点,问过其他点后,他的所有出边连的点身份都清楚了。
如果有杀手,就不用问他了。
如果没有杀手,因为大小为
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int tot, ver[N << 1], nxt[N << 1], head[N];
int n, m, dfn[N], low[N], in[N];
int cnt, sc, scc[N], stk[N], siz[N], top;
bool instk[N];
vector <int> E[N];
void add(int x, int y) {
ver[++ tot] = y;
nxt[tot] = head[x];
head[x] = tot;
}
void tarjan(int x) {
low[x] = dfn[x] = ++ cnt;
stk[++ top] = x; instk[x] = 1;
for (int i = head[x], y; i; i = nxt[i]) {
y = ver[i];
if (!dfn[y]) {
tarjan(y);
low[x] = min(low[x], low[y]);
} else if (instk[y])
low[x] = min(low[x], dfn[y]);
}
if (low[x] == dfn[x]) {
sc ++;
while (top && stk[top] != x) {
scc[stk[top]] = sc;
instk[stk[top]] = 0;
siz[sc] ++;
top --;
}
scc[stk[top]] = sc;
instk[stk[top]] = 0;
siz[sc] ++;
top --;
}
}
int main() {
cin >> n >> m;
for (int i = 1, u, v; i <= m; i ++) {
cin >> u >> v;
add(u, v);
}
for (int i = 1; i <= n; i ++) {
if (dfn[i]) continue;
tarjan(i);
}
for (int i = 1; i <= n; i ++)
for (int j = head[i]; j; j = nxt[j])
if (scc[i] != scc[ver[j]]) {
in[scc[ver[j]]] ++;
E[scc[i]].push_back(scc[ver[j]]);
}
double ans = 1, N = n;
int c = 0;
bool flg = 0;
for (int i = 1; i <= sc; i ++) {
if (in[i]) continue;
c ++;
if (siz[c] > 1) continue;
if (flg) continue;
bool ok = 1;
for (auto v : E[i])
if (in[v] <= 1) ok = 0;
if (ok) c --, flg = 1;
}
ans = 1.0 - 1.0 * c / N;
cout << fixed << setprecision(6) << ans << "\n";
return 0;
}
本文来自博客园,作者:maniubi,转载请注明原文链接:https://www.cnblogs.com/maniubi/p/18393844,orz
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】