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. Java开发桌面程序学习(10)——css样式表使用以及Button使用

    css 样式表使用 javafx中的css样式,与html的有些不一样,javafx中的css,是以-fx-background-color这种样子的,具体可以参考文档JavaFx css官方文档 简 ...

  2. service mesh学习规划

    istio go语言 谷歌开发 现有产品功能(每个功能具体支持哪些方式,优缺点) 服务注册发现 流量劫持 路由 负载均衡 熔断降级 流量控制(限流.流量分配) 重试机制 日志管理 支持的协议 监控(健 ...

  3. Express 中配置使用 art-template模板引擎

    art-template 官网 https://aui.github.io/art-template/ 安装: npm install --save art-template npm install ...

  4. [NOI2007]社交网络(最短路)

    [NOI2007]社交网络 Description 在社交网络(socialnetwork)的研究中,我们常常使用图论概念去解释一些社会现象.不妨看这样的一个问题. 在一个社交圈子里有n个人,人与人之 ...

  5. mysql数据按条件导出

    仅导出部分数据: mysqldump -hlocalhost -uuser -p --skip-triggers --no-create-info dbname tbname -w "id ...

  6. MacOS系統Flutter打包apk

    一.打包前需要做一些基本设置的确认 1.应用名 2.权限设置 3.applicationId:应用唯一标识符 4.versionCode:版本号 5.versionName:版本名称 6.APP应用图 ...

  7. configerparser模块

    '''[mysqld]charater-server-set='utf8'default-engine='innodb'skip-grant-table=Trueport=3306 [client]u ...

  8. if和switch的选择结构

    1. Java中的if选择结构,包括以下形式. *基本if选择结构:可以处理一单一或组合条件的情况. *if-else选择结构:可以处理简单的条件分支情况. *多重if选择结构:可以处理连续区间的条件 ...

  9. 20180711-Java分支结构 – if…else/switch

    public class Test{ public static void main(String args[]){ int x = 10; if(x<20){ System.out .prin ...

  10. php面试专题---MySQL分表

    php面试专题---MySQL分表 一.总结 一句话总结: 分库分表要数据达到一定的量级才用,这样才有效率,不然利不一定大于弊,可能会增加一次I/O消耗 1.分库分表的使用量级是多少? 单表行数超过 ...