可惜没如果=_=
不知那年的樱花树上,哪一瓣最美

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

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2647  Solved: 769
[Submit][Status][Discuss]

Description

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

Input

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

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

概率题……laj不会哇……

首先如果构成一个环的话,只要调查环中的任意一个人,整个环的信息都可以知道,所以先缩点,缩点以后入度为0的点是一定要调查的ans+=入度为0的点的个数;,在这些点中有特殊情况,就是如果当前点(缩点后的点)只包含一个点,并且他的儿子的入度都不为1的话这个点可调查可不调查ans--;qwq

假设最坏情况这些调查的点全部都可能是杀人犯,所以最后的概率为(n-ans)/n;

laj的code迷之WA 从对拍的结果来看大概100个点中有两个点WA吧 _(:зゝ∠)_ 应该是tarjan的bug  然而laj实在是找不出来了 _(:зゝ∠)_

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 typedef long long LL;
 4 const int MAX1=1e5+5;
 5 const int MAX2=3e5+5;
 6 int n,m;
 7 int tot,head[MAX1],adj[MAX2],next[MAX2];
 8 int tx,cnt,dfn[MAX1],low[MAX1],fro[MAX1],sta[MAX1],size[MAX1],du[MAX1];
 9 bool vis[MAX1],ins[MAX1];
10 struct Edge{int u,v;}edge[MAX2];
11 inline int read(){
12     int an=0,x=1;char c=getchar();
13     while (c<'0' || c>'9') {if (c=='-') x=-1;c=getchar();}
14     while (c>='0' && c<='9') {an=(an<<3)+(an<<1)+c-'0';c=getchar();}
15     return an*x;
16 }
17 void addedge(int u,int v){
18     tot++;adj[tot]=v,next[tot]=head[u],head[u]=tot;
19 }
20 void tarjan(int x,int fa){
21     dfn[x]=low[x]=++tx;
22     vis[x]=ins[x]=true;sta[++sta[0]]=x;
23     int i,j;
24     for (i=head[x];i;i=next[i]){
25         if (adj[i]==fa) continue;
26         if (!vis[adj[i]]){
27             tarjan(adj[i],x);
28             low[x]=min(low[x],low[adj[i]]);
29         }
30         else if (ins[adj[i]])
31             low[x]=min(low[x],dfn[adj[i]]);
32     }
33     if (low[x]>=dfn[x]){
34         ++cnt;
35         do{++size[cnt];fro[sta[sta[0]]]=cnt,ins[sta[sta[0]]]=false;}
36         while (sta[sta[0]--]!=x);
37     }
38 }
39 int main(){
40     freopen ("murder.in","r",stdin);freopen ("murder.out","w",stdout);
41     int i,j,u,v,ans=0;
42     n=read(),m=read();
43     for (i=1;i<=m;i++){
44         edge[i].u=read(),edge[i].v=read();
45         addedge(edge[i].u,edge[i].v);
46     }
47     for (i=1;i<=n;i++) if (!vis[i]) tarjan(i,0);
48     for (i=1;i<=m;i++) if (fro[edge[i].u]!=fro[edge[i].v])du[fro[edge[i].v]]++;
49     for (i=1;i<=cnt;i++)
50         if (!du[i]) ans++;
51     for (i=1;i<=n;i++)
52         if (size[fro[i]]==1 && du[fro[i]]==0){
53             for (j=head[i];j;j=next[j])
54                 if (du[fro[adj[j]]]<=1) break;
55             if (!j) {ans--;break;}
56         }
57     printf("%.6lf",(double)(n-ans)/n);
58     return 0;
59 }

 

posted on 2017-10-27 23:52  珍珠鸟  阅读(99)  评论(0编辑  收藏