説明
冷血キラーをNa-wiatに潜入、及び市民のふり。警察は殺人者である人を見つける、内部N個体であることを願っています。皆のための警察の缶は
、検証対象は民間人であれば、彼は民間人であるキラー、である彼は知っていた警察が、言うだろう検証することでした。オブジェクトが検証殺すことであれば
、手を、キラーは警察を取り除くでしょう。警察は現在、すべての個人を習得誰だか知っています。誰もが殺人犯は、彼らが確率されていると見ることができ、おそらくキラーを持っている
割合が同じです。Q:独自のセキュリティを確保するための最良の環境によると、警察は殺人最大確率はどのくらいが誰であるか知っていますか?
\(N \ 10 ^ 5、m個の\ 3 \タイムズ10 ^ 5 \)
溶液
最適戦略がチェック仮定\(X \)次に、確率は、人の未知のアイデンティティを( - \ FRAC {X N \ \ {N})
だから我々はできるだけ少数の人々をチェックします。
まず、強連結成分のために、限り、人は完了したすべてのセキュリティチェックのこの強連結成分を確認することができますよう。
だから、最初のラフが捜査のDAG点0度の完全な還元のすべての点を考慮して、殺人犯を見つけることができるようになります。
そして、それはこのハックになります。
3 2
2 1
3 1
最高の検索2と3を確認したが、わずか2または3をチェックしません。
だから、慎重に考えて、一つであり、それも外れ度ポイントがどこにあるかがあれば、少なくともポイントは強連結成分に独自のサイズを満たすためにことがわかった(\ 1>)\、このポイントがチェックされていない、チェックする必要があります番号は1になります。
複数のこのような点がある場合でも、これらは最後に残ったポイントでなければなりませんので、数だけ、調査は1つだけだっ減少しますが、私たちは判断できないことに注意してください誰がキラー(または、彼らはより高い価格を支払うことになるかどうかをチェック)。
コード
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <fstream>
typedef long long LL;
typedef unsigned long long uLL;
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define MP(x, y) std::make_pair(x, y)
#define DE(x) cerr << x << endl;
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define GO cerr << "GO" << endl;
using namespace std;
inline void proc_status()
{
ifstream t("/proc/self/status");
cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>()) << endl;
}
inline int read()
{
register int x = 0; register int f = 1; register char c;
while (!isdigit(c = getchar())) if (c == '-') f = -1;
while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar()));
return x * f;
}
template<class T> inline void write(T x)
{
static char stk[30]; static int top = 0;
if (x < 0) { x = -x, putchar('-'); }
while (stk[++top] = x % 10 xor 48, x /= 10, x);
while (putchar(stk[top--]), top);
}
template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
const int maxN = 2e5 + 2;
int n, m;
int stk[maxN], top;
int low[maxN], dfn[maxN], dfst;
int in[maxN], size[maxN], cnt, col[maxN];
vector<int> g[maxN];
void link(int u, int v) { g[u].push_back(v); }
void tarjan(int u)
{
int v;
dfn[u] = low[u] = ++dfst;
stk[++top] = u;
for (int i = 0; i < SZ(g[u]); ++i)
{
v = g[u][i];
if (!dfn[v])
tarjan(v), chkmin(low[u], low[v]);
else if (!col[v])
chkmin(low[u], dfn[v]);
}
if (low[u] == dfn[u])
{
++cnt;
do
{
v = stk[top--];
col[v] = cnt;
size[cnt]++;
} while (u != v);
}
}
bool chk(int u)
{
if (size[col[u]] != 1) return 0;
if (in[col[u]]) return 0;
for (int i = 0; i < SZ(g[u]); ++i)
{
int v = g[u][i];
if (in[col[v]] <= 1)
return 0;
}
return 1;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("xhc.in", "r", stdin);
freopen("xhc.out", "w", stdout);
#endif
n = read(), m = read();
for (int i = 1; i <= m; ++i) { int u = read(), v = read(); link(u, v); }
for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i);
for (int i = 1; i <= n; ++i)
for (int j = 0; j < SZ(g[i]); ++j)
if (col[g[i][j]] != col[i])
in[col[g[i][j]]]++;
int ans = 0, delta = 0;
for (int i = 1; i <= cnt; ++i) if (!in[i]) ans++;
for (int i = 1; i <= n; ++i) if (chk(i)) delta++;
if (delta) printf("%.6lf\n", (double)(n - ans + 1) / n);
else printf("%.6lf\n", (double) (n - ans) / n);
return 0;
}