bzoj2438[中山市选2011]杀人游戏
2016-08-14 11:28
375 查看
Description
一位冷血的杀手潜入 Na-wiat,并假装成平民。警察希望能在 N 个人里面,查出谁是杀手。
警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他
认识的人, 谁是杀手, 谁是平民。 假如查证的对象是杀手, 杀手将会把警察干掉。
现在警察掌握了每一个人认识谁。
每一个人都有可能是杀手,可看作他们是杀手的概率是相同的。
问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多
少?
Input
第一行有两个整数 N,M。接下来有 M 行,每行两个整数 x,y,表示 x 认识 y(y 不一定认识 x,例如胡锦涛同志) 。
Output
仅包含一行一个实数,保留小数点后面 6 位,表示最大概率。Sample Input
5 41 2
1 3
1 4
1 5
Sample Output
0.800000HINT
警察只需要查证 1。假如1是杀手,警察就会被杀。假如 1不是杀手,他会告诉警察 2,3,4,5 谁是杀手。而 1 是杀手的概率是 0.2,所以能知道谁是杀手但没被杀的概
率是0.8。对于 100%的数据有 1≤N ≤ 10 0000,0≤M ≤ 30 0000
数据已加强!
思路:本人初中党表示对概率这东西不是很懂。。。
大神的题解:http://www.cnblogs.com/xkui/p/4552391.html
题目的关键在于要想到,既然是关系问题(思考一下并查集是否可以解?不能,我认为出现了“x 认识 y(y 不一定认识 x,例如胡锦涛同志)”表明不可用),就涉及到只要是几个人构成了有向图强联通分量,那么质问其中一人就可以得知所有的分量内的关系,缩一下点就没有必要枚举所有人。而此时,直接去问那些入度为0的分量。至于为什么可以参照这个公式哦:
ans=(n-1)/n(第一次问不是罪犯)*[(s1-1/n-1)(集合在第一点集中)+((n-s1)/(n-1))*((n-s1-1)/(n-s1))*((s2-1)*(n-s1-1))(分别为,不在第一点集,第二次不问到罪犯,在第二点集的概率)+...]。(问入度为0的点集可以保证它们之间互补相干)。
当然此题程序也并非单纯的模板
特判:当有一个分量只包括一个点、入度为0且不影响其他分量的入度是否为0(似乎不是桥),那么当其他点问过后,就不用关心这个点了,从ans中删除它的增量1。
1590224
ksq2013 | 2438 | Accepted | 37256 kb | 1032 ms | C++/Edit | 2083 B | 2016-08-14 11:08:14 |
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int n,m,first[1000111],du[1000111],sz[1000111],hd[1000111],ecnt,ans=0; int pre[1000111],sccn[1000111],lowlink[1000111],mstack[1000111],stack_cnt,dfs_clock,scc_cnt; struct edge{ int u,v,nxt; }e[300333]; void link(int u,int v) { e[++ecnt].u=u; e[ecnt].v=v; e[ecnt].nxt=first[u]; first[u]=ecnt; } void dfs(int u) { int v; pre[u]=lowlink[u]=++dfs_clock; mstack[++stack_cnt]=u; for(int i=first[u];i;i=e[i].nxt){ v=e[i].v; if(!pre[v]){ dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); } else if(!sccn[v]) lowlink[u]=min(lowlink[u],pre[v]); } if(!(pre[u]^lowlink[u])){ hd[++scc_cnt]=u; do{ v=mstack[stack_cnt--]; sccn[v]=scc_cnt; ++sz[scc_cnt]; }while(v^u); } } void tarjan() { memset(pre,0,sizeof(pre)); memset(sccn,0,sizeof(sccn)); memset(lowlink,0,sizeof(lowlink)); stack_cnt=dfs_clock=scc_cnt=0; for(int i=1;i<=n;i++) if(!pre[i]) dfs(i); } bool jud(int u) { for(int i=first[u];i;i=e[i].nxt) if(du[sccn[e[i].v]]==1) return 0; return 1; } int main() { memset(sz,0,sizeof(sz)); memset(du,0,sizeof(du)); memset(first,0,sizeof(first)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); link(u,v); } tarjan(); for(int i=1;i<=ecnt;i++) if(sccn[e[i].u]^sccn[e[i].v]) ++du[sccn[e[i].v]]; for(int i=1;i<=scc_cnt;i++) if(!du[i]) ++ans; for(int i=1;i<=scc_cnt;i++)//special judge; if(!du[i]&&sz[i]==1&&jud(hd[i])) {--ans;break;} printf("%.6lf\n",(double)(n-ans)/n); return 0; }
相关文章推荐
- BZOJ 2438 [中山市选2011] 杀人游戏 (图的联通,tarjan)
- [BZOJ 2438] 中山市选2011 杀人游戏 · Tarjan
- 【BZOJ2438】[中山市选2011]杀人游戏 Tarjan
- bzoj2438: [中山市选2011]杀人游戏(强联通)
- BZOJ 2438 中山市选 2011 杀人游戏 Tarjan
- bzoj2438 [中山市选2011]杀人游戏
- 【BZOJ2438】【中山市选2011】杀人游戏 强连通分量+期望
- BZOJ_2438_[中山市选2011]杀人游戏 _强连通分量
- [bzoj2438][中山市选2011]杀人游戏
- [BZOJ 2438] [中山市选2011]杀人游戏 Tarjan缩点
- [强联通] bzoj 2438: [中山市选2011]杀人游戏
- bzoj 2438: [中山市选2011]杀人游戏 强连通分量
- [bzoj 2438--中山市选2011]杀人游戏
- BZOJ——2438: [中山市选2011]杀人游戏
- BZOJ 2438 [中山市选2011] 杀人游戏 题解与分析
- [bzoj 2438][中山市选2011]杀人游戏 概率+tarjan
- BZOJ 2438 [中山市选2011]杀人游戏 ——期望DP
- 【bzoj2438】【中山市选2011】【杀人游戏】【强连通分量缩点】
- BZOJ 2438 中山市选2011 杀人游戏 Tarjan
- 【bzoj2438】[中山市选2011]杀人游戏 Tarjan