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;
}
posted @ 2020-09-18 10:46  Gensokyo_Alice  阅读(121)  评论(0编辑  收藏  举报