[bzoj2438][中山市选2011]杀人游戏
2017-05-25 20:33
337 查看
来自FallDream的博客,未经允许,请勿转载,谢谢。
一位冷血的杀手潜入 Na-wiat,并假装成平民。警察希望能在 N 个人里面,查出谁是杀手。
警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民。 假如查证的对象是杀手, 杀手将会把警察干掉。
现在警察掌握了每一个人认识谁。 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的。
问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少?
n<=100000 m<=300000
tarjan缩点之后,推一波公式,发现只要查的是入度为0的点,顺序并没有影响。
要特殊处理的是大小为1的点。当然一个联通块也有可能在查了一个人之后剩下的部分大小是1。我们可以把入度为0的点按照大小排序之后从大到小dfs,就可以找到这种情况。
答案是(n-入度为0的点的个数+是否有大小为1的点)/n
一位冷血的杀手潜入 Na-wiat,并假装成平民。警察希望能在 N 个人里面,查出谁是杀手。
警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民。 假如查证的对象是杀手, 杀手将会把警察干掉。
现在警察掌握了每一个人认识谁。 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的。
问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少?
n<=100000 m<=300000
tarjan缩点之后,推一波公式,发现只要查的是入度为0的点,顺序并没有影响。
要特殊处理的是大小为1的点。当然一个联通块也有可能在查了一个人之后剩下的部分大小是1。我们可以把入度为0的点按照大小排序之后从大到小dfs,就可以找到这种情况。
答案是(n-入度为0的点的个数+是否有大小为1的点)/n
#include<iostream> #include<cstdio> #include<algorithm> #define MN 200000 using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } bool mark[MN+5],inq[MN+5]; int cnt=0,dn=0,cc,in[MN+5],sum=0,head[MN+5],size[MN+5],q[MN+5],top=0,bel[MN+5],n,m,dfn[MN+5],low[MN+5]; struct edge{int to,next;}e[MN*3+5]; inline void ins(int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;} void tarjan(int x) { dfn[x]=low[x]=++dn;q[++top]=x;inq[x]=1; for(int i=head[x];i;i=e[i].next) if(!dfn[e[i].to]) tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]); else if(inq[e[i].to]) low[x]=min(low[x],dfn[e[i].to]); if(dfn[x]==low[x]) for(++cc;q[top+1]!=x;bel[q[top]]=cc,inq[q[top]]=0,++size[cc],--top); } bool cmp(int x,int y){return size[x]>size[y];} void Dfs(int x) { sum+=size[x];mark[x]=1; for(int i=head[x];i;i=e[i].next) if(!mark[e[i].to]) Dfs(e[i].to); } int main() { cc=n=read();m=read(); for(int i=1;i<=m;++i) { int x=read(),y=read(); ins(x,y); } for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;++i) for(int j=head[i];j;j=e[j].next) if(bel[i]!=bel[e[j].to]) ins(bel[i],bel[e[j].to]),++in[bel[e[j].to]]; for(int i=n+1;i<=cc;++i) if(!in[i]) q[++top]=i; sort(q+1,q+top+1,cmp); int ans=n-top; for(int i=1;i<=top;++i) { sum=0;Dfs(q[i]); if(sum==1) {++ans;break;} } printf("%.6lf",(double)ans/n); return 0; }
相关文章推荐
- bzoj 2438: [中山市选2011]杀人游戏 强连通分量
- [bzoj 2438--中山市选2011]杀人游戏
- BZOJ——2438: [中山市选2011]杀人游戏
- [bzoj 2438][中山市选2011]杀人游戏 概率+tarjan
- bzoj 2438: [中山市选2011]杀人游戏【tarjan】
- 【bzoj2438】【中山市选2011】【杀人游戏】【强连通分量缩点】
- BZOJ 2438 中山市选2011 杀人游戏 Tarjan
- 【bzoj2438】[中山市选2011]杀人游戏 Tarjan
- bzoj2438 [中山市选2011]杀人游戏(tarjan缩点)
- BZOJ2438: [中山市选2011]杀人游戏
- BZOJ 2438 [中山市选2011]杀人游戏 ——期望DP
- bzoj2438[中山市选2011]杀人游戏
- bzoj 2438: [中山市选2011]杀人游戏(Tarjan)
- bzoj 2438: [中山市选2011]杀人游戏 (强联通分量 Tarjan)
- bzoj2438[中山市选2011]杀人游戏
- bzoj 2438 [中山市选2011]杀人游戏(SCC+概率)
- BZOJ 2438 [中山市选2011] 杀人游戏 (图的联通,tarjan)
- [BZOJ 2438] 中山市选2011 杀人游戏 · Tarjan
- BZOJ 2438 [中山市选2011] 杀人游戏 题解与分析
- 【BZOJ2438】[中山市选2011]杀人游戏 Tarjan