2438: [中山市选2011]杀人游戏
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
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 }