P4819 [中山市選]殺人遊戲
阿新 • • 發佈:2018-10-23
但是 多少 一個 根據 ble 自身 縮點 eof ret
題目描述
一位冷血的殺手潛入Na-wiat,並假裝成平民。警察希望能在NN個人裏面,查出誰是殺手。警察能夠對每一個人進行查證,假如查證的對象是平民,他會告訴警察,他認識的人,誰是殺手,誰是平民。假如查證的對象是殺手,殺手將會把警察幹掉。現在警察掌握了每一個人認識誰。每一個人都有可能是殺手,可看作他們是殺手的概率是相同的。
問:根據最優的情況,保證警察自身安全並知道誰是殺手的概率最大是多少?
Solution
首先縮點, 然後需要把縮完點後的DAG上每個入度為0的點都詢問一次才行.
但是有一種特殊情況是有一個入度為0的點, 它連接的點都不是必須需要它.這時就可以不詢問它了.
Code
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> const int N = 1e5 + 5, M = 3e5 + 6; class BaseGraph { public: struct Edge { int v; Edge* nxt; Edge(int _, Edge* __) : v(_), nxt(__) { } } *head[N]; int du[N]; BaseGraph() { memset(du, false, sizeof du); for (int i = 1; i < N; i += 1) head[i] = nullptr; } void AddEdge(int u, int v) { du[v] += 1; head[u] = new Edge(v, head[u]); } }; class Graph : public BaseGraph { int dfn[N], low[N], vis[N], que[N], col[N], siz[N]; int vis_num, col_num, top; void Tarjan(int u) { dfn[u] = low[u] = ++vis_num; vis[u] = true, que[++top] = u; for (auto edge = head[u]; edge; edge = edge->nxt) { if (not dfn[edge->v]) Tarjan(edge->v), low[u] = std:: min(low[u], low[edge->v]); else if (vis[edge->v]) low[u] = std:: min(low[u], low[edge->v]); } if (dfn[u] == low[u]) { vis[u] = false, col[u] = ++col_num, siz[col_num] = 1; while (que[top] != u) vis[que[top]] = false, col[que[top--]] = col_num, siz[col_num] += 1; top--; } } public: double init(int n, int m) { for (int i = 0, u, v; i < m; i += 1) { scanf("%d%d", &u, &v); AddEdge(u, v); } for (int i = 1; i <= n; i += 1) if (not dfn[i]) Tarjan(i); BaseGraph* rG = new BaseGraph(); for (int u = 1; u <= n; u += 1) for (auto edge = head[u]; edge; edge = edge->nxt) if (col[u] != col[edge->v]) rG->AddEdge(col[u], col[edge->v]); int num_without_du = 0; for (int i = 1; i <= col_num; i += 1) if (not rG->du[i]) num_without_du += 1; for (int u = 1; u <= n; u += 1) if (not rG->du[col[u]] and siz[col[u]] == 1) { bool flag = false; for (auto edge = head[u]; edge; edge = edge->nxt) { if (rG->du[col[edge->v]] == 1) { flag = true; break; } } if (not flag) { return 1.0 - 1.0 * (num_without_du - 1) / n; } } return 1.0 - 1.0 * num_without_du / n; } }; int main () { int n, m; Graph* G = new Graph(); scanf("%d%d", &n, &m); printf("%.6f\n", G->init(n, m)); return 0; }
P4819 [中山市選]殺人遊戲