[bzoj 2438][中山市选2011]杀人游戏 概率+tarjan
2017-07-27 20:45
423 查看
考试的时候想了很多,不知道它那个概率究竟是怎么算。。没想到能蒙30分。rp爆发hhh
题解转自不知道哪里来的老师发的(代码出自自己)。
实际上警察就是两种结果——查到犯人或死亡,而死亡事件一定是包含在“调查未知身份的人”,也就是说调查未知身份的人越多,死亡概率就越高,所以我们要求的问题就是警察要尽可能少调查未知身份的人
给出公式 P(死亡)=调查的未知身份的人数/总人数
“死亡”和”存活”是对立事件,而”存活”等价于”找到犯人” 所以 ans=1−P死亡 问题转化为求调查最少的未知身份人的人数
同时我们发现,对于一个环(1认识2,2认识3,3认识1),我们是可以把他们看作一个人的,也就是说,只要调查了他们其中一个,其他两个我们一定可以安全到达(知道他是犯人或平民) 对于这个问题,我们使用tarjan对图进行缩点处理,然后我们所要调查的对象就是重构图中那些入度为0的点(没有人知道这些点里的人的身份),调查的未知身份的人数就是这些点的数量 (如果其中入度不为0,那么我们一定可以从一个入度为0的点走到这里,即我们调查这个点时是知道这里面的人的身份的)
注意:
有一个特殊情况,如果说至少有一个点,它只有一个人,他是完全孤立的(即没有人知道这个人的身份,他对外面的世界也一无所知)或者他认识的每个人都被除他以外的其他人所认识(即它所能到达的点的入度>1),那么我们在安全调查完除他以外的其他人后,他一定是杀手(但在图上他属于未知身份的人),我们不必去调查他,直接抓起来就可以了,所以调查未知身份的人数要– 1(我们可以想得简单些,比如n=1时这个人一定是杀手,即P存活=1)
题解转自不知道哪里来的老师发的(代码出自自己)。
实际上警察就是两种结果——查到犯人或死亡,而死亡事件一定是包含在“调查未知身份的人”,也就是说调查未知身份的人越多,死亡概率就越高,所以我们要求的问题就是警察要尽可能少调查未知身份的人
给出公式 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 ,dfn ,stack ,instack ,belong ; int peo ; struct haha{ int next,to; }; haha edgechu ,edge ; int head ,cnt=1,cntchu=1,headchu ; 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 ,out ; int ans; int flag ; 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)
- 2438: [中山市选2011]杀人游戏 tarjan+概率与期望
- BZOJ 2438 中山市选2011 杀人游戏 Tarjan
- 【BZOJ2438】[中山市选2011]杀人游戏 Tarjan
- bzoj 2438: [中山市选2011]杀人游戏【tarjan】
- BZOJ 2438 中山市选 2011 杀人游戏 Tarjan
- bzoj 2438 [中山市选2011]杀人游戏(SCC+概率)
- BZOJ 2438 [中山市选2011] 杀人游戏 (图的联通,tarjan)
- 【bzoj2438】[中山市选2011]杀人游戏 Tarjan
- bzoj 2438: [中山市选2011]杀人游戏(Tarjan)
- [BZOJ 2438] 中山市选2011 杀人游戏 · Tarjan
- [BZOJ 2438] [中山市选2011]杀人游戏 Tarjan缩点
- bzoj2438 [中山市选2011]杀人游戏(tarjan缩点)
- bzoj2438: [中山市选2011]杀人游戏(强联通)
- BZOJ——2438: [中山市选2011]杀人游戏
- 【BZOJ2438】【中山市选2011】杀人游戏 强连通分量+期望
- bzoj 2438: [中山市选2011]杀人游戏 强连通分量
- bzoj2438[中山市选2011]杀人游戏
- bzoj2438[中山市选2011]杀人游戏
- BZOJ 2438 [中山市选2011] 杀人游戏 题解与分析