[bzoj 2438][中山市选2011]杀人游戏 概率+tarjan
考试的时候想了很多,不知道它那个概率究竟是怎么算。。没想到能蒙30分。rp爆发hhh
题解转自不知道哪里来的老师发的(代码出自自己)。
实际上警察就是两种结果——查到犯人或死亡,而死亡事件一定是包含在“调查未知身份的人”,也就是说调查未知身份的人越多,死亡概率就越高,所以我们要求的问题就是警察要尽可能少调查未知身份的人
给出公式 P(死亡)=调查的未知身份的人数/总人数
“死亡”和”存活”是对立事件,而”存活”等价于”找到犯人” 所以 ans=1−P死亡 问题转化为求调查最少的未知身份人的人数
同时我们发现,对于一个环(1认识2,2认识3,3认识1),我们是可以把他们看作一个人的,也就是说,只要调查了他们其中一个,其他两个我们一定可以安全到达(知道他是犯人或平民) 对于这个问题,我们使用tarjan对图进行缩点处理,然后我们所要调查的对象就是重构图中那些入度为0的点(没有人知道这些点里的人的身份),调查的未知身份的人数就是这些点的数量 (如果其中入度不为0,那么我们一定可以从一个入度为0的点走到这里,即我们调查这个点时是知道这里面的人的身份的)
注意:
有一个特殊情况,如果说至少有一个点,它只有一个人,他是完全孤立的(即没有人知道这个人的身份,他对外面的世界也一无所知)或者他认识的每个人都被除他以外的其他人所认识(即它所能到达的点的入度>1),那么我们在安全调查完除他以外的其他人后,他一定是杀手(但在图上他属于未知身份的人),我们不必去调查他,直接抓起来就可以了,所以调查未知身份的人数要– 1(我们可以想得简单些,比如n=1时这个人一定是杀手,即P存活=1)
#include<cstdio> #include<cstring> #include<iostream> using namespace std; #define pos(i,a,b) for(int i=(a);i<=(b);i++) #define N 500000 int n,m; int low[N],dfn[N],stack[N],instack[N],belong[N]; int peo[N]; struct haha{ int next,to; }; haha edgechu[N],edge[N]; int head[N],cnt=1,cntchu=1,headchu[N]; void add(int u,int v){ edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } void addchu(int u,int v){ edgechu[cntchu].to=v; edgechu[cntchu].next=headchu[u]; headchu[u]=cntchu++; } int ji=1,hea,cn=1; void tarjan(int now){ low[now]=dfn[now]=ji++; stack[++hea]=now; instack[now]=1; for(int i=headchu[now];i;i=edgechu[i].next){ int to=edgechu[i].to; if(dfn[to]==-1){ tarjan(to); low[now]=min(low[now],low[to]); } else{ if(instack[to]){ low[now]=min(low[now],dfn[to]); } } } if(low[now]==dfn[now]){ int temp; while(1){ temp=stack[hea--]; belong[temp]=cn; instack[temp]=0; peo[cn]++; if(temp==now) break; } cn++; } } int in[N],out[N]; int ans; int flag[N]; int main(){ freopen("killer.in","r",stdin); freopen("killer.out","w",stdout); scanf("%d%d",&n,&m); memset(dfn,-1,sizeof(dfn)); pos(i,1,m){ int x,y; scanf("%d%d",&x,&y); addchu(x,y); } pos(i,1,n){ if(dfn[i]==-1) tarjan(i); } cn--; pos(i,1,n){ for(int v=headchu[i];v;v=edgechu[v].next){ int j=edgechu[v].to; if(belong[i]!=belong[j]){ add(belong[i],belong[j]); in[belong[j]]++; out[belong[i]]++; } } } pos(i,1,cn){ if(in[i]==0){ ans++; } } pos(i,1,cn){ if(peo[i]==1){ if(in[i]==0&&out[i]==0){ ans--; double temp=(double)(n-ans)/n; printf("%0.6lf",temp); return 0; } else{ for(int j=head[i];j;j=edge[j].next){ int to=edge[j].to; if(in[to]>1){ flag[i]++; } } if(flag[i]==out[i]&&(flag[i])){ ans--; double temp=(double)(n-ans)/n; printf("%0.6lf",temp); return 0; } } } } double temp=(double)(n-ans)/n; printf("%0.6lf",temp); return 0; }
[bzoj 2438][中山市选2011]杀人游戏 概率+tarjan的更多相关文章
- bzoj 2438: [中山市选2011]杀人游戏【tarjan】
没看太懂题意orz 最优的是tarjan缩点之后问入度为0的点,因为问这个点可以知道整个块的情况 答案是这ans个入度为0的点都不是杀手的概率\( \frac{n-ans}{n} \) 但是有特殊情况 ...
- bzoj 2438 [中山市选2011]杀人游戏(SCC+概率)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2438 [题意] N个人中有一个杀手,每次询问一个人可能被杀或被告知其认识的人中谁是杀手 ...
- BZOJ——2438: [中山市选2011]杀人游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=2438 Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个 ...
- BZOJ 2438: [中山市选2011]杀人游戏
Description 给你一个有向图,求至少询问多少次能够得到全部点的信息. Sol Tarjan + 强连通分量缩点 + 判断. 先缩点,如果我们知道了强连通分量里的任意一个点,我们就可以知道这些 ...
- [BZOJ 2438] [中山市选2011]杀人游戏 Tarjan缩点
这个题很容易想到正解就是缩点找入度为零的点,那么我们考虑一种特殊情况就是,一个入度为零的点我们不访问他就知道他是不是凶手,那么这样的话就是:I. 他是一个真·孤立的点 II. 他在图里但是在他的强联通 ...
- BZOJ 2438 [中山市选2011]杀人游戏 ——期望DP
发现每一次死亡的几率相等,所以只需要判断最少问多少人即可. 并且环上的点任意询问都可以. 所以直接Tarjan缩点,然后计算入度为0的点的数目. 但是还有一些情况的时候会减少一次询问,比如说:$1-& ...
- bzoj2438: [中山市选2011]杀人游戏(强联通+特判)
2438: [中山市选2011]杀人游戏 题目:传送门 简要题意: 给出n个点,m条有向边,进行最少的访问并且可以便利(n-1)个点,求这个方案成功的概率 题解: 一道非常好的题目! 题目要知道最大的 ...
- BZOJ_2438_[中山市选2011]杀人游戏 _强连通分量
BZOJ_2438_[中山市选2011]杀人游戏 _强连通分量 Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手.警察能够对每一个人 ...
- bzoj2438[中山市选2011]杀人游戏
Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面, 查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他 认识的人, ...
随机推荐
- 探索Windows命令行系列(6):活用批处理解决实际问题
1.批量修改文件名 2.批量重启服务 3.全盘搜索指定文件 3.1.全盘搜索名称为 mm.jpg 的文件,获取其全路径 3.2.查找系统中所有名称以 .docx 结尾的文件 4.调用可执行程序 4.1 ...
- JavaScript对象属性访问的两种方式
JavaScript对象属性访问的两种方式 object.attribute object["attribute"] 例如: var employees = [ { "f ...
- app 选项卡代码
<div id="segmented" class="mui-segmented-control"> <a class="mui-c ...
- Openfire插件开发图解
概述 Openfire插件开发是Openfire的精髓之一,支持插件热插拔,还可以方便的在web端进行管理插件.插件分为两种,一种是以服务为主的控制台插件,一种是包括页面或对外开放Servlet接口. ...
- canvas学习总结五:线段的端点与连接点
我们在第三节中描述了线段的绘制,其中线段的属性lineWidth是用来改变线段的宽度.让我们来回忆下线宽的用法 function drawLine(){ cxt.lineWidth = 3; cxt. ...
- 揭开Socket编程的面纱(留着自己慢慢看)
对TCP/IP.UDP.Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵.那么我想问: 1. 什么是TCP/IP.UDP?2. Socket在哪里呢?3. Socket ...
- CCS学习(三)
边框样式 边框线 dorder-style (top 上: bottom 下: left 左: right 右) 样式:none | hidden | dotted | dashed | sol ...
- 我的学习之路_第二十九章_bootstrap
bootstrap 内置了html,css,js插件为一体的前端框架 响应式布局: 设计一套页面就可以使用于很多现实设备 bootstrap: 1.入门(响应式布局的容器) 1.先进入jQuery的j ...
- java Semaphore的介绍和使用
一个计数信号量.从概念上讲,信号量维护了一个许可集.如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可.每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者. ...
- 一个简单的时间轴demo
一个时间轴的组成 使用一个块级元素包裹内容,并未块级元素设置边框 定义圆形或者菱形等元素标签,子元素设置偏移或者定位元素将图标定位到边框上 使其中的内容不溢出,自动换行,内容自动撑高 英文自动换行:w ...