bzoj2438 杀人游戏 Tarjan强联通

【bzoj2438】[中山市选2011]杀人游戏

Description

一位冷血的杀手潜入 Na-wiat,并假装成平民。警察希望能在 N 个人里面,
查出谁是杀手。
警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他
认识的人, 谁是杀手, 谁是平民。 假如查证的对象是杀手, 杀手将会把警察干掉。
现在警察掌握了每一个人认识谁。
每一个人都有可能是杀手,可看作他们是杀手的概率是相同的。
问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多
少?

Input

第一行有两个整数 N,M。
接下来有 M 行,每行两个整数 x,y,表示 x 认识 y(y 不一定认识 x,例如同志) 。

Output

仅包含一行一个实数,保留小数点后面 6 位,表示最大概率。

Sample Input

5 4
1 2
1 3
1 4
1 5

Sample Output

0.800000

HINT

警察只需要查证 1。假如1是杀手,警察就会被杀。假如 1不是杀手,他会告诉警
察 2,3,4,5 谁是杀手。而 1 是杀手的概率是 0.2,所以能知道谁是杀手但没被杀的概
率是0.8。

对于 100%的数据有 1≤N ≤  10 0000,0≤M ≤  30 0000

题解

在一个强联通中,可以一步一步推出每个人,所以只需要知道一个人就可以了,然后就是入度为0的点有关了。

ans=入度为0的连通块个数

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn=1e5+5,maxm=3e5+5;
 5
 6 int pre[maxn],low[maxn],scc[maxn],clock,cnt;
 7 int head[maxn],f[maxm],e[maxm],nxt[maxm],k;
 8 int adde(int u,int v){
 9     e[++k]=v,f[k]=u;
10     nxt[k]=head[u],head[u]=k;
11 }
12 int n,m,r[maxn],a[maxn],t;
13 int size[maxn],num[maxn];
14
15 int dfs(int u){
16     pre[u]=low[u]=++clock;
17     a[++t]=u;
18     for(int i=head[u];i;i=nxt[i]){
19         int v=e[i];
20         if(!pre[v]){
21             dfs(v);
22             low[u]=min(low[u],low[v]);
23         }
24         else if(!scc[v]){
25             low[u]=min(low[u],pre[v]);
26         }
27     }
28     if(low[u]==pre[u]){
29         num[++cnt]=u;
30         while(t){
31             scc[a[t]]=cnt;
32             size[cnt]++;
33             if(a[t--]==u) break;
34         }
35     }
36 }
37
38 int pd(int x){
39     int u=num[x];
40     for(int i=head[u];i;i=nxt[i])
41         if(r[scc[e[i]]]==1) return 0;
42     return 1;
43 }
44
45 int main(){
46     scanf("%d%d",&n,&m);
47     int u,v;
48     for(int i=1;i<=m;i++){
49         scanf("%d%d",&u,&v);
50         adde(u,v);
51     }
52
53     for(int i=1;i<=n;i++)
54         if(!pre[i]) dfs(i);
55
56     for(int i=1;i<=k;i++)
57         if(scc[f[i]]!=scc[e[i]]) r[scc[e[i]]]++;
58
59     int ans=0;
60     for(int i=1;i<=cnt;i++)
61         if(!r[i]) ans++;
62
63     for(int i=1;i<=cnt;i++)
64         if(size[i]==1&&!r[i]&&pd(i)){
65             ans--;
66             break;
67         }
68
69     printf("%.6lf",(double)(n-ans)/n);
70     return 0;
71 }

原文地址:https://www.cnblogs.com/fengzhiyuan/p/8326159.html

时间: 2024-10-14 05:20:12

bzoj2438 杀人游戏 Tarjan强联通的相关文章

bzoj 2438: [中山市选2011]杀人游戏 (强联通分量 Tarjan)

Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌握了每一个人认识谁. 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的. 问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少? Input 第一行有两个整数 N,M. 接下来有 M 行,每行两个整数 x

[中山市选]杀人游戏 Tarjan+概率

[中山市选]杀人游戏 Tarjan+概率 题目描述 ? 一位冷血的杀手潜入\(Na\)-\(wiat\),并假装成平民.警察希望能在\(N\)个人里面,查出谁是杀手.警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人,谁是杀手,谁是平民.假如查证的对象是杀手,杀手将会把警察干掉.现在警察掌握了每一个人认识谁.每一个人都有可能是杀手,可看作他们是杀手的概率是相同的. 问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少? 输入输出格式 输入格式: ? 第一行有

【BZOJ2438】[中山市选2011]杀人游戏 Tarjan

[BZOJ2438][中山市选2011]杀人游戏 Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌握了每一个人认识谁. 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的. 问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少? Input 第一行有两个

【BZOJ-2438】杀人游戏 Tarjan + 缩点 + 概率

2438: [中山市选2011]杀人游戏 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1638  Solved: 433[Submit][Status][Discuss] Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌

BZOJ 2438 中山市选 2011 杀人游戏 Tarjan

题目大意:给出一张有向人物关系图,告诉你谁认识谁,认识具有传递性.其中有一个人是犯人.现在警察要调查谁是犯人.他可以问任何人.但是如果他问到了犯人,那么它就会死.如果他问到的一个人认识犯人,这个人就会告诉警察谁是犯人.问警察保证自身安全并知道犯人是谁的概率最大是多少. 思路:这个题前一阵子重测了,加强了数据,卡掉了网上一片AC代码.. 正解并不是很难想.首先先缩点,整个图变成拓扑图,之后会出现一些类似根的东西,这些scc入度为0,只要警察询问了这些scc每一个中的任意一个,就肯定能知道谁是犯人.

BZOJ 2438 中山市选2011 杀人游戏 Tarjan

题目大意:有n个人,其中一个是杀手,可以询问一些人,如果是杀手就会死,如果是平民,他会告诉你他认识的人中有谁是杀手有谁是平民 警告:数据有误,请谨慎提交! 易知如果我需要访问x个人,那么答案就是1-x/n 我们需要访问最少的人 如果我访问的人是平民,那么这个点所有的后继我都能知道 于是Tarjan缩点之后入度为零的点就是答案 但是还有一个问题 比如说这组样例 3 1 1 2 我访问了1,那么1和2是不是凶手我就都知道了 既然只有三个人,我知道1和2是不是凶手,那么3也一定知道 没必要去访问3 于

tarjan 强联通分量和割点

1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<ctime> 5 #include<iostream> 6 #include<algorithm> 7 #include<queue> 8 #include<stack> 9 #include<set> 10 #define esp (1e-6) 11 #defin

Tarjan强联通分量【模板】

1 #include <algorithm> 2 #include <cstdio> 3 4 using namespace std; 5 6 const int N(100015); 7 int n,m,v,u; 8 int edgesum,head[N]; 9 10 struct Edge 11 { 12 int from,to,next; 13 Edge(int from=0,int to=0,int next=0) : 14 from(from),to(to),next(n

[BZOJ2438]杀人游戏(缩点+特判)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2438 分析:如果出现了环,那么只要询问环上的一个人,那么环上其他的人的信息也就知道了,所以相当于一个点,于是先缩点成一个DAG图. 对于这个DAG图,我们可以知道最优的情况就是询问那些入度为0的点,那么接下来的点就能全部确定了,但是每询问一个点,失败的概率就会增加1/n,所以ans=1-入度为0的点的个数*(1/n) 但是有特殊的情况,如果有个点它缩点前是一个点并且它的出边指向的边的