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

http://www.lydsy.com/JudgeOnline/problem.php?id=2438

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


数据已加强!

 

Source

 

杀手与村民为对立事件,警察存活概率=1-p(被杀), p(被杀)=可能为杀手的人数/n

因为警察根据最优情况选人,那么求出scc,警察第一个人会选择入度为零的scc,算出这些scc成为杀手的概率即可

(一个scc成为杀手的概率为 1/n ,因为在一个scc中问一个人就可以知道此块中的所有信息)

特别的:如果存在一个独立的scc(可以根据访问别的人判断此块信息,即该块只有一个人,连出去的点的入读>1),

则该scc不需要统计,因为可以通过别的推断出,即 cnt--

 1 #include <cstdio>
 2 
 3 #define min(a,b) (a<b?a:b)
 4 
 5 inline void read(int &x)
 6 {
 7     x=0; register char ch=getchar();
 8     for(; ch>'9'||ch<'0'; ) ch=getchar();
 9     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
10 }
11 
12 const int N(100005);
13 const int M(300005);
14 
15 int n,m,sumedge,cnt;
16 int head[N],_v[M<<1],_nex[M<<1];
17 
18 inline void ins(int u,int v)
19 {
20     _v[++sumedge]=v;
21     _nex[sumedge]=head[u];
22     head[u]=sumedge;
23 }
24 
25 int tim,dfn[N],low[N],rd[N];
26 int top,Stack[N],instack[N];
27 int sumcol,col[N],point[N];
28 
29 void DFS(int u)
30 {
31     dfn[u]=low[u]= ++tim;
32     Stack[++top]=u; instack[u]=1;
33     for(int i=head[u]; i; i=_nex[i])
34     {
35         if(!dfn[_v[i]]) DFS(_v[i]),low[u]=min(low[u],low[_v[i]]);
36         else if(instack[_v[i]]) low[u]=min(low[u],dfn[_v[i]]);
37     }
38     if(low[u]!=dfn[u]) return ;
39     point[col[u]= ++sumcol] ++;
40     for(; Stack[top]!=u; --top)
41     {
42         point[sumcol]++;
43         instack[Stack[top]]=0;
44         col[Stack[top]]=sumcol;
45     }
46     instack[u]=0, --top;
47 }
48 
49 int Presist()
50 {
51     read(n),read(m);
52     for(int u,v,i=1; i<=m; ++i)
53         read(u),read(v),ins(u,v);
54     for(int i=1; i<=n; ++i)
55         if(!dfn[i]) DFS(i);
56     for(int u=1; u<=n; ++u)
57       for(int i=head[u]; i; i=_nex[i])
58           if(col[u]!=col[_v[i]]) rd[col[_v[i]]]++;
59     for(int i=1; i<=sumcol; ++i) cnt+=(!rd[i]);
60     for(int u=1; u<=n; ++u)
61     {
62         if(rd[col[u]]||point[col[u]]>1) continue;
63         for(int i=head[u]; i; i=_nex[i])
64              if(rd[col[_v[i]]]<2) goto next_;
65         cnt--; break; next_:;
66     }
67     printf("%.6lf\n",1*1.-1.*cnt/n);
68     return 0;
69 }
70 
71 int Aptal=Presist();
72 int main(int argc,char**argv){;}

 

posted @ 2017-11-19 14:55  Aptal丶  阅读(226)  评论(0编辑  收藏  举报