Description

一位冷血的杀手潜入 Na-wiat,并假装成平民。警察希望能在 N 个人里面,查出谁是杀手。警察能够对每一个人

进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民。 假如查证的对象是杀

手, 杀手将会把警察干掉。现在警察掌握了每一个人认识谁。每一个人都有可能是杀手,可看作他们是杀手的概

率是相同的。问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少?

\(n\le 10^5, m\le 3\times 10^5\)

Solution

假设最优策略查了 \(x\) 个未知身份的人,那么概率就是 \(\frac{n - x}{n}\)

所以我们尽可能的查少的人。

首先,对于一个强连通分量,只要查一个人就可以把这个强连通分量全部安全查完。

所以先粗略考虑把每一个缩完点的一个个dag中入度为0的点查了,那么一定可以把杀手找出来。

然后就会被这个hack:

3 2
2 1
3 1

发现最优不是查2和3,而是仅查2或3。

于是仔细一想,发现若存在至少一个点满足它自己所在的强连通分量大小为1且它连出去的点的入度都 \(> 1\) ,那么这个点是不用查的,所以需要查的人数就会-1。

注意就算存在多个这样的点,查的人数也仅仅只会减少1,因为最后剩下的一定是这些点,而我们无法确定谁是杀手(否则查他们的话会付出更大的代价)。

Code

#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;
}

[BZOJ2438]杀人游戏的更多相关文章

  1. bzoj2438 杀人游戏 Tarjan强联通

    [bzoj2438][中山市选2011]杀人游戏 Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手.警察能够对每一个人进行查证,假如查 ...

  2. [BZOJ2438]杀人游戏(缩点+特判)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2438 分析:如果出现了环,那么只要询问环上的一个人,那么环上其他的人的信息也就知道了, ...

  3. 【强连通分量+概率】Bzoj2438 杀人游戏

    Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是 ...

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

    2438: [中山市选2011]杀人游戏 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1638  Solved: 433[Submit][Statu ...

  5. 【BZOJ2438】[中山市选]杀人游戏 Tarjan+概率

    [中山市选]杀人游戏 Tarjan+概率 题目描述 ​ 一位冷血的杀手潜入\(Na\)-\(wiat\),并假装成平民.警察希望能在\(N\)个人里面,查出谁是杀手.警察能够对每一个人进行查证,假如查 ...

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

    2438: [中山市选2011]杀人游戏 题目:传送门 简要题意: 给出n个点,m条有向边,进行最少的访问并且可以便利(n-1)个点,求这个方案成功的概率 题解: 一道非常好的题目! 题目要知道最大的 ...

  7. hdu2211杀人游戏

    Problem Description 不知道你是否玩过杀人游戏,这里的杀人游戏可没有法官,警察之类的人,只有土匪,现在已知有N个土匪站在一排,每个土匪都有一个编号,从1到N,每次杀人时给定一个K值, ...

  8. 丢沙包游戏(或杀人游戏)的C语言实现

    丢沙包游戏(或杀人游戏)用C语言实现: 游戏简述: 杀人游戏(或者丢沙包游戏),设定一些人(人数为:num)一起玩游戏,从某个指定的人(设定为:start)开始轮流扔沙包,扔沙包人的下一个人为1,每隔 ...

  9. 杀人游戏(hdu2211)插入法

    杀人游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

随机推荐

  1. socket中TCP的三次握手连接和四次握手释放

    三次握手连接 A: 我进来了啊 B:(有人来了安排个位子)回复:好的你进来吧 A:好的: 客户端向服务器发送一个SYN J 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1 客户 ...

  2. 前端开发HTML&css入门——常用的标签以及一个小练习

    meta标签 <!doctype html> <html> <head> <meta charset="utf-8" /> < ...

  3. php WebService应用

    <?php header ( "Content-Type: text/html; charset=gb2312" ); /* * 指定WebService路径并初始化一个We ...

  4. python在类中使用__slot__属性

    在类中定义__slot__属性来限制实例的属性字段,在创建大量对象的场合可以减少内存占用. 创建大量对象是内存占用对比: 类中不使用__slot__ class MySlot:def __init__ ...

  5. android 打卡 虚拟定位 sqlite

    1.使用android5.1模拟器 android5.1模拟器使用数据库管理参数文件,6.0及以后的版本使用xml文件管理 2.使用sqlite修改配置文件 3.修改secure库中的android_ ...

  6. [APIO2009]抢掠计划(Tarjan,SPFA)

    [APIO2009]抢掠计划 题目描述 Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是, ...

  7. 【学习】006数据交换格式与SpringIOC底层实现

    课程目标 XML和JSON Java反射机制 手写SpringIOC 什么是数据交换格式 客户端与服务器常用数据交换格式xml.json.html 数据交换格式用场景 移动端(安卓.IOS)通讯方式采 ...

  8. stream benchmark 交叉编译 on psoc

    之前有研究过这个,居然忘记了,看来确实是老了,没有盘过来. 如何下载,见 linux下载网页上的文件夹以及删除文件(stream) 出现了好几个问题 1. error while loading sh ...

  9. 01.helloworld--标签

    """参考网站:http://python.cocos2d.org/doc/programming_guide/index.html""" ...

  10. maven推送本地包到私服

    前置要求:配置正确的settings.xml maven 推送 本地jar 到私服的命令示例: mvn deploy:deploy-file -DgroupId=com.oracle -Dartifa ...