Description

一位冷血的杀手潜入Na-wiat,并假装成平民。警察希望能在\(N\)个人里面,查出谁是杀手。警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人,谁是杀手,谁是平民。假如查证的对象是杀手,杀手将会把警察干掉。现在警察掌握了每一个人认识谁。每一个人都有可能是杀手,可看作他们是杀手的概率是相同的。

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

Input

第一行有两个整数 \(N,M\)。 接下来有\(M\)行,每行两个整数 \(x,y\),表示 \(x\) 认识 \(y\)(\(y\) 不一定认识 \(x\) ,例如President同志) 。

Output

仅包含一行一个实数,保留小数点后面 \(6\) 位,表示最大概率。

首先,如果一些人之间的关系存在环,那么我们可以只问其中的一个人就能知道这个环中的所有人的身份.可以降低我们的被害几率.

环?\(Tarjan\)缩点.

考虑到直接算安全的概率可能比较难算,所以我们考虑单步容斥.

安全概率=1-被杀概率

\(Tarjan\)缩点之后我们再次建图,会得到一个拓扑图.

这个拓扑图中,对于入度为\(0\)的一个点.显然,其会对被害几率有贡献.

因此我们记录图中入度为\(0\)的点的个数.

但是会存在一种情况,类似这样.

显然这个时候如果我们从左上角的点开始调查,发现没有杀手.

则杀手必定在下边的点中(这个点\(size\)必须为1,并且与其相连的点必须有其他入度).

确保自身安全的情况下,我们已经知道了杀手是谁.因此,这种点对答案并没有贡献.

且至多会有一个,

在代码中判断一下即可.

代码

#include<cstdio>
#include<cctype>
#include<iostream>
#define N 100008
#define R register
using namespace std;
inline void in(int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int n,m,head[N],tot,ttt,h[N],size[N],col;
struct cod{int u,v;}edge[N<<5],e[N<<2];
inline void add(int x,int y)
{
edge[++tot].u=head[x];
edge[tot].v=y;
head[x]=tot;
}
inline void ado(int x,int y)
{
e[++ttt].u=h[x];
e[ttt].v=y;
h[x]=ttt;
}
int dfn[N],low[N],top,idx,stk[N],ins[N],now,belong[N];
bool inq[N],flg;
void tarjan(int u)
{
dfn[u]=low[u]=++idx;
stk[++top]=u;inq[u]=true;
for(R int i=head[u];i;i=edge[i].u)
{
if(!dfn[edge[i].v])
{
tarjan(edge[i].v);
low[u]=min(low[u],low[edge[i].v]);
}
else if(inq[edge[i].v])
low[u]=min(low[u],dfn[edge[i].v]);
}
if(low[u]==dfn[u])
{
int now=-1;col++;
while(now!=u)
{
now=stk[top--];
size[col]++;
inq[now]=false;
belong[now]=col;
}
}
}
inline bool pd(int x)
{
for(R int i=h[x];i;i=e[i].u)
if(ins[e[i].v]==1)return false;
return true;
}
int ans;
int main()
{
in(n),in(m);
for(R int i=1,x,y;i<=m;i++)
{
in(x),in(y);
add(x,y);
}
for(R int i=1;i<=n;i++)
if(!dfn[i])tarjan(i);
for(R int x=1;x<=n;x++)
for(R int i=head[x];i;i=edge[i].u)
if(belong[edge[i].v]!=belong[x])
ins[belong[edge[i].v]]++,ado(belong[x],belong[edge[i].v]);
for(R int x=1;x<=col;x++)
{
if(!flg and size[x]==1 and !ins[x] and pd(x))flg=true;
if(!ins[x])ans++;
}
if(flg)ans--;
printf("%.6f",1-(double)((double)ans/(double)n));
}

Tarjan缩点【p4819】[中山市选]杀人游戏的更多相关文章

  1. 洛谷 P4819 [中山市选]杀人游戏(tarjan缩点)

    P4819 [中山市选]杀人游戏 思路分析 题意最开始理解错了(我太菜了) 把题意简化一下,就是找到可以确定杀手身份的最小的危险查看数 (就是不知道该村名的身份,查看他的身份具有危险的查看数量),用 ...

  2. 洛谷 P4819 [中山市选]杀人游戏

    洛谷 题目就是让我们在DAG中找到一些点,覆盖所有点. 因为是DAG,可以想到tarjan缩一下点.假设我们需要找x个点,那么答案就是(n-x)/n. 我们怎么选点呢? 敏锐的我们很快就能想到,直接选 ...

  3. P4819 [中山市选]杀人游戏

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

  4. [洛谷P4819][中山市选]杀人游戏

    题目大意:有一张$n$个点$m$条边的有向图,有一个关键点,如果你访问一个点,你会知道它连出的边中有没有关键点,以及若有的话是哪个.问最优策略下不访问关键点而知道关键点的概率 题解:发现若一个点不是关 ...

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

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

  6. [中山市选]杀人游戏 (Tarjan缩点)

    题目链接 Solution 可以考虑到如果知道环内一点的身份,如果凶手在其中就查出来了,同时不会有危险. 那么对警察造成威胁的就是那些身份不明且不能从其他点转移过来的点. 那么大部答案就是缩完点之后入 ...

  7. LG4819/BZOJ2438 「中山市选2011」杀人游戏 Tarjan缩点+概率

    问题描述 LG4819 BZOJ2438 题解 发现如果有一些人之间认识关系形成环,只需要问一个人就能把控整个环. \(\mathrm{Tarjan}\)缩点. 缩点之后所有入度为\(0\)的点,必须 ...

  8. bzoj 2438: [中山市选2011]杀人游戏【tarjan】

    没看太懂题意orz 最优的是tarjan缩点之后问入度为0的点,因为问这个点可以知道整个块的情况 答案是这ans个入度为0的点都不是杀手的概率\( \frac{n-ans}{n} \) 但是有特殊情况 ...

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

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

随机推荐

  1. 编译gearman提示缺少boost

    编译german时提示缺少boost: checking for boostlib >= 1.39... configure: We could not detect the boost lib ...

  2. 玩转Openstack之Nova中的协同并发(二)

    玩转Openstack之Nova中的协同并发(二) 昨天介绍了Python中的并发处理,主要介绍了Eventlet,今天就接着谈谈Openstack中Nova对其的应用. eventlet 在nova ...

  3. canda 常用命令

    1.获取版本 conda -V conda --version 2.获取帮助 conda -h conda --help 查看某一命令的帮助 conda install -h conda instal ...

  4. APPIUM-----自动发现兼容的Chromedrivers

    使用Appium Desired Capabilities:chromedriverExecutableDir chromeDriver所有版本下载路径:https://chromedriver.st ...

  5. Heat 如何来实现和支持编排

    编排 编排,顾名思义,就是按照一定的目的依次排列.在 IT 的世界里头,一个完整的编排一般包括设置服务器上机器.安装 CPU.内存.硬盘.通电.插入网络接口.安装操作系统.配置操作系统.安装中间件.配 ...

  6. ssh 免交互登录 ,远程执行命令脚本。

    ##免交互SSH登录auto_login_ssh () {    expect -c "set timeout -1;                spawn -noecho ssh -o ...

  7. 破解navicat

    每次试用版也真的是烦,注册机试过一次后,又提示注册 果断选择其他方法 官网先下载一个正版 再下patchNavicat.exe 安装完navicat后直接点击patchNavicat 选择navica ...

  8. Access连接字符串

    Access2007没有密码连接: <connectionStrings> <add name="myconn" connectionString="P ...

  9. atom-安装插件

    1. 安装git. 2. 安装node环境,其中集成了npm. 3. 启动git 键入命令: cd User/[yourname]/.atom/packages 进入packages目录. 4. 下载 ...

  10. vi - vim的一些遗忘点

    1. vi 供分为三种模式:一般模式.编辑模式和命令行模式.i / Esc + :wq :q :q! 使vi在一般模式与编辑模式中来回转换. /word 向下寻找一个名称为word的字符串: ?wor ...