考试的时候想了很多,不知道它那个概率究竟是怎么算。。没想到能蒙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. Vue.js 介绍入门

    Vue.js 的目标 是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件.Vue.js 是一个用于创建 Web 交互界面的库.它让你通过简单而灵活的 API 创建由数据驱动的 UI 组件. ...

  2. zookeeper client API实现(python kazoo 的实现)

    这里主要分析zookeeper client API的实现方式,以python kazoo的实现代码为蓝本进行逻辑分析. 一.代码框架及介绍 API分为同步模式和异步模式.同步模式是在异步模式的基础上 ...

  3. JavaScript从入门到忘记

    JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. 一.如何编写 二.变 ...

  4. win7-x64安装mysql5.7.11(官方zip版)

    1.下载官方安装包(http://www.mysql.com/downloads/),此zip包是没有安装器的(*.msi),也没有辅助配置的自动程序. 2.解压zip包,将文件放入指定目录,如:D: ...

  5. My sql添加远程用户root密码为password

    添加远程用户root密码为password grant all privileges on *.* to root@localhost identified by '123321' with gran ...

  6. java操作DBF的使用

    1.引入javadbf.4.1.jar 2. import com.linuxense.javadbf.DBFField;   import com.linuxense.javadbf.DBFRead ...

  7. CISCO2960配置vlan

    一.VTP配置 1.VLAN database 2.(VLAN)#vtp domain wx 3.(VLAN)#vtp server 二.VLAN配置 1.VLAN database 2.(VLAN) ...

  8. CentOS 6.8重新安装yum

    问题来源:我在虚拟机上安装vncserver,输入yum install tigervnc tigervnc-server出现问题,所以就重新安装了一遍yum. 具体的过程看如下这个链接:http:/ ...

  9. Carbondata源码系列(一)文件生成过程

    在滴滴的两年一直在加班,人也变懒了,就很少再写博客了,最近在进行Carbondata和hive集成方面的工作,于是乎需要对Carbondata进行深入的研究. 于是新开一个系列,记录自己学习Carbo ...

  10. 输入3个数a,b,c,按大小顺序输出

    题目:输入3个数a,b,c,按大小顺序输出 package com.li.FiftyAlgorthm; import java.util.Scanner; /** * 题目:输入3个数a,b,c,按大 ...