P4819 [中山市选]杀人游戏
P4819 中山市选 杀人游戏
简单来说就是找到入度为0的点记为 \(cnt\)
那么我们可以缩点直接找,不然复杂度爆炸。
答案是 \(ans = 1.0 - frac{cnt}{N}\) (这是错的)
但是这是错的,因为少考虑一种情况。
你是可以推理的!!!!!!!!
那末,我们考虑这样一组数据
100 0
答案显然是1%(只有最后一个人不是杀手),因为你要一个人一个人去查,那末你只用查99个人,最后一个人是不是杀手就显然。
形式化的,当且仅当一个人不会影响调查,而且缩点后 \(siz = 1\) 的时候,他可以被推理出来,但是你只能选一个这样的点(显然)。
所以记一个 \(flag\) 看有没有这样的人。
真实答案就是 \(ans = 1.0 - \frac{cnt - flag}{N}\)
然后要去掉重边(缩点后的)。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <stack>
#include <map>
using namespace std;
typedef long long ll;
const ll MAXN = 1e6+10;
ll N, M;
struct edge {
ll nt, to;
} E[MAXN], E2[MAXN];
ll ind[MAXN], ond[MAXN], siz[MAXN];
ll head[MAXN], cnt = -1, dfn[MAXN], low[MAXN], num, vis[MAXN], _N, head2[MAXN], cnt2 = -1, bel[MAXN];
stack <ll> st;
map <ll, ll> m[MAXN];
void add(ll, ll);
void add2(ll, ll);
void rebuild();
void tarjan(ll);
bool iss(ll);
int main() {
memset(head2, -1, sizeof(head2));
memset(head, -1, sizeof(head));
scanf("%lld%lld", &N, &M);
for (ll x, y, i = 1; i <= M; i++) {
scanf("%lld%lld", &x, &y);
add(x, y);
}
for (ll i = 1; i <= N; i++) {
if (!dfn[i])
tarjan(i);
}
rebuild();
ll ct = 0, flag = 0;
for (ll i = 1; i <= _N; i++) {
if (!ind[i]) {
ct++;
if (siz[i] == 1 && (!ond[i] || iss(i))) {
flag = 1;
}
}
}
printf("%.6f", 1.0 - (1.0 * (ct - flag) / N));
return 0;
}
bool iss(ll n) {
for (ll i = head2[n]; ~i; i = E2[i].nt) {
ll v = E2[i].to;
if (ind[v] == 1) return false;
}
return true;
}
void rebuild() {
for (ll i = 1; i <= N; i++) {
for (ll j = head[i]; ~j; j = E[j].nt) {
ll v = E[j].to;
if (bel[v] != bel[i]) {
if (m[bel[i]][bel[v]]) continue;
m[bel[i]][bel[v]] = 1;
add2(bel[i], bel[v]);
ind[bel[v]]++;
ond[bel[i]]++;
}
}
}
}
void add2(ll x, ll y) {
cnt2++;
E2[cnt2].to = y;
E2[cnt2].nt = head2[x];
head2[x] = cnt2;
}
void tarjan(ll n) {
dfn[n] = low[n] = ++num;
st.push(n);
for (ll i = head[n]; ~i; i = E[i].nt) {
ll v = E[i].to;
if (vis[v]) continue;
if (dfn[v]) {
low[n] = min(dfn[v], low[n]);
} else {
tarjan(v);
low[n] = min(low[n], low[v]);
}
}
if (low[n] == dfn[n]) {
ll t;
_N++;
do {
t = st.top(); st.pop();
bel[t] = _N;
vis[t] = 1;
siz[_N]++;
} while (t != n);
}
}
void add(ll x, ll y) {
cnt++;
E[cnt].to = y;
E[cnt].nt = head[x];
head[x] = cnt;
}
希望我们都有一个光明的未来