P4819 [中山市选]杀人游戏

题目描述

一位冷血的杀手潜入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;
}

原文地址:https://www.cnblogs.com/qdscwyy/p/9835474.html

时间: 2024-10-19 16:29:40

P4819 [中山市选]杀人游戏的相关文章

[中山市选]杀人游戏 Tarjan+概率

[中山市选]杀人游戏 Tarjan+概率 题目描述 ? 一位冷血的杀手潜入\(Na\)-\(wiat\),并假装成平民.警察希望能在\(N\)个人里面,查出谁是杀手.警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人,谁是杀手,谁是平民.假如查证的对象是杀手,杀手将会把警察干掉.现在警察掌握了每一个人认识谁.每一个人都有可能是杀手,可看作他们是杀手的概率是相同的. 问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少? 输入输出格式 输入格式: ? 第一行有

[中山市选2011]杀人游戏

[中山市选2011]杀人游戏 时间限制: 1 Sec  内存限制: 128 MB提交: 64  解决: 33[提交][状态][讨论版] 题目描述 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌握了每一个人认识谁. 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的. 问:根据最优的情况,保

【BZOJ2438】[中山市选2011]杀人游戏 Tarjan

[BZOJ2438][中山市选2011]杀人游戏 Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌握了每一个人认识谁. 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的. 问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少? Input 第一行有两个

bzoj2438: [中山市选2011]杀人游戏(强联通+特判)

2438: [中山市选2011]杀人游戏 题目:传送门 简要题意: 给出n个点,m条有向边,进行最少的访问并且可以便利(n-1)个点,求这个方案成功的概率 题解: 一道非常好的题目! 题目要知道最大的存活概率,那么也就是找到直接找到杀手的最小概率 那么我们采用强联通缩点: 统计每个联通分量的入度,如果入度为0(证明除此联通分量里的点,没有人可以知道连通分量里的信息,那就一定要先选一个人访问),那么sum++(因为依据题意,假如问到连通分量里的任意一个人,只要ta不是杀手,那么一定可以安全的遍历强

BZOJ2464: 中山市选[2009]小明的游戏

2464: 中山市选[2009]小明的游戏 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 280  Solved: 124[Submit][Status] Description 小 明最近喜欢玩一个游戏.给定一个n * m的棋盘,上面有两种格子#和@.游戏的规则很简单:给定一个起始位置和一个目标位置,小明每一步能向上,下,左,右四个方向移动一格.如果移动到同一类 型的格子,则费用是0,否则费用是1.请编程计算从起始位置移动到目标位置的最小花费.

bzoj2464: 中山市选[2009]小明的游戏(最短路)

2464: 中山市选[2009]小明的游戏 题目:传送门 题解: 最短路的裸题... 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 int dx[5]={0,1,-1,0,0}; 8 int dy[5]={0,0,0,-1,1}; 9 st

【BZOJ-2438】杀人游戏 Tarjan + 缩点 + 概率

2438: [中山市选2011]杀人游戏 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1638  Solved: 433[Submit][Status][Discuss] Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌

杀人游戏

问题 C: [中山市选2011]杀人游戏 题目描述 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌握了每一个人认识谁. 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的. 问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少? 输入 第一行有两个整数 N,M. 接下来有 M

bzoj2438 杀人游戏 Tarjan强联通

[bzoj2438][中山市选2011]杀人游戏 Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手.警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉.现在警察掌握了每一个人认识谁.每一个人都有可能是杀手,可看作他们是杀手的概率是相同的.问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少? Input 第一行有两个整数 N