考试的时候想了很多,不知道它那个概率究竟是怎么算。。没想到能蒙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的更多相关文章

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

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

  2. bzoj 2438 [中山市选2011]杀人游戏(SCC+概率)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2438 [题意] N个人中有一个杀手,每次询问一个人可能被杀或被告知其认识的人中谁是杀手 ...

  3. BZOJ——2438: [中山市选2011]杀人游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=2438 Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个 ...

  4. BZOJ 2438: [中山市选2011]杀人游戏

    Description 给你一个有向图,求至少询问多少次能够得到全部点的信息. Sol Tarjan + 强连通分量缩点 + 判断. 先缩点,如果我们知道了强连通分量里的任意一个点,我们就可以知道这些 ...

  5. [BZOJ 2438] [中山市选2011]杀人游戏 Tarjan缩点

    这个题很容易想到正解就是缩点找入度为零的点,那么我们考虑一种特殊情况就是,一个入度为零的点我们不访问他就知道他是不是凶手,那么这样的话就是:I. 他是一个真·孤立的点 II. 他在图里但是在他的强联通 ...

  6. BZOJ 2438 [中山市选2011]杀人游戏 ——期望DP

    发现每一次死亡的几率相等,所以只需要判断最少问多少人即可. 并且环上的点任意询问都可以. 所以直接Tarjan缩点,然后计算入度为0的点的数目. 但是还有一些情况的时候会减少一次询问,比如说:$1-& ...

  7. bzoj2438: [中山市选2011]杀人游戏(强联通+特判)

    2438: [中山市选2011]杀人游戏 题目:传送门 简要题意: 给出n个点,m条有向边,进行最少的访问并且可以便利(n-1)个点,求这个方案成功的概率 题解: 一道非常好的题目! 题目要知道最大的 ...

  8. BZOJ_2438_[中山市选2011]杀人游戏 _强连通分量

    BZOJ_2438_[中山市选2011]杀人游戏 _强连通分量 Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手.警察能够对每一个人 ...

  9. bzoj2438[中山市选2011]杀人游戏

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

随机推荐

  1. JAVA上传与下载

    java下载指定地址的文件 package com.test; import java.io.FileNotFoundException; import java.io.FileOutputStrea ...

  2. grep[行号&正则匹配字符有颜色]

    事情是这样的,昨天在深入学习grep命令时,看到别人博客用grep正则匹配,不仅行数有颜色,而且匹配到的字符也有颜色.我在CRT也试了下,毛颜色都没有.顿时感觉 so low. 解决 编辑vim~/. ...

  3. Docker部署DVWA

    上次在Docker手动配置了一个Ubuntu的Lamp镜像,这次来试验一下使用这个镜像部署一个简单的web应用吧. 首先从Lamp镜像运行一个容器 root@VM-149-127-debian:~/a ...

  4. 初试spring-session

    一.简介 spring-session提供了用户会话信息管理的API和实现. 它将取代容器中的HttpSession.在没有容器会话集群方案的情况下,使得支持会话集群微不足道. 它支持在一个浏览器实例 ...

  5. AT&T汇编helloworld

    摘自:http://blog.163.com/guixl_001/blog/static/417641042012112102642703/ 代码: #hello.s .data # 数据段声明 ms ...

  6. 基于 svn 服务器及 cocoapods-repo-svn 插件进行组件化私有库的创建

    一.准备 组件化 随着业务需求的增长,在单工程 MVC 模式下,app 代码逐渐变得庞大,面对的高耦合的代码和复杂的功能模块,我们或许就需要进行重构了,以组件化的形式,将需要的组件以 pod 私有库的 ...

  7. 拥抱.NET Core系列:Logging (1)

    在之前我们简单介绍了 .NET Core 中的 DI组件,没来及了解的童鞋可以翻翻我之前的文章. 接下来会对 .NET Core 中的 Logging 进行介绍. 本文中使用了"Micros ...

  8. Tkinter开发第一个桌面程序HelloWorld

    在Python3中是tkinter,Python2中是Tkinter Tkinter是Python 官方承认的标准 GUI 方案(de-facto standard),因为是Python自带安装,决定 ...

  9. css display:box 新属性

    一.display:box; 在元素上设置该属性,可使其子代排列在同一水平上,类似display:inline-block;. 二.可在其子代设置如下属性 前提:使用如下属性,必须在父代设置displ ...

  10. Abp(.NetCore)开发与发布过程

    .NetCore 项目开发正当火热,ABP也推出了.NetCore的版本.趁此机会学习.NetCore的开发与发布过程.以下是本人的踩坑经验. 在ABP官网提供单页面应用开发框架(AngularJs) ...