一位冷血的杀手潜入 Na-wiat,并假装成平民。警察希望能在 N 个人里面,查出谁是杀手。警察能够对每一个人
进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民。 假如查证的对象是杀
手, 杀手将会把警察干掉。现在警察掌握了每一个人认识谁。每一个人都有可能是杀手,可看作他们是杀手的概
率是相同的。问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少?
+= 小数点 target esc script tchar ont 一个 中山市选
第一行有两个整数 N,M。
接下来有 M 行,每行两个整数 x,y,表示 x 认识 y(y 不一定认识 x,例如周恩来同志) 。
仅包含一行一个实数,保留小数点后面 6 位,表示最大概率。
警察只需要查证 1。假如1是杀手,警察就会被杀。假如 1不是杀手,他会告诉警
察 2,3,4,5 谁是杀手。而 1 是杀手的概率是 0.2,所以能知道谁是杀手但没被杀的概
率是0.8。对于 100%的数据有 1≤N ≤ 10 0000,0≤M ≤ 30 0000
数据已加强!
杀手与村民为对立事件,警察存活概率=1-p(被杀), p(被杀)=可能为杀手的人数/n
因为警察根据最优情况选人,那么求出scc,警察第一个人会选择入度为零的scc,算出这些scc成为杀手的概率即可
(一个scc成为杀手的概率为 1/n ,因为在一个scc中问一个人就可以知道此块中的所有信息)
特别的:如果存在一个独立的scc(可以根据访问别的人判断此块信息,即该块只有一个人,连出去的点的入读>1),
则该scc不需要统计,因为可以通过别的推断出,即 cnt--
- #include <cstdio>
- #define min(a,b) (a<b?a:b)
- inline void read(int &x)
- {
- x=0; register char ch=getchar();
- for(; ch>‘9‘||ch<‘0‘; ) ch=getchar();
- for(; ch>=‘0‘&&ch<=‘9‘; ch=getchar()) x=x*10+ch-‘0‘;
- }
- const int N(100005);
- const int M(300005);
- int n,m,sumedge,cnt;
- int head[N],_v[M<<1],_nex[M<<1];
- inline void ins(int u,int v)
- {
- _v[++sumedge]=v;
- _nex[sumedge]=head[u];
- head[u]=sumedge;
- }
- int tim,dfn[N],low[N],rd[N];
- int top,Stack[N],instack[N];
- int sumcol,col[N],point[N];
- void DFS(int u)
- {
- dfn[u]=low[u]= ++tim;
- Stack[++top]=u; instack[u]=1;
- for(int i=head[u]; i; i=_nex[i])
- {
- if(!dfn[_v[i]]) DFS(_v[i]),low[u]=min(low[u],low[_v[i]]);
- else if(instack[_v[i]]) low[u]=min(low[u],dfn[_v[i]]);
- }
- if(low[u]!=dfn[u]) return ;
- point[col[u]= ++sumcol] ++;
- for(; Stack[top]!=u; --top)
- {
- point[sumcol]++;
- instack[Stack[top]]=0;
- col[Stack[top]]=sumcol;
- }
- instack[u]=0, --top;
- }
- int Presist()
- {
- read(n),read(m);
- for(int u,v,i=1; i<=m; ++i)
- read(u),read(v),ins(u,v);
- for(int i=1; i<=n; ++i)
- if(!dfn[i]) DFS(i);
- for(int u=1; u<=n; ++u)
- for(int i=head[u]; i; i=_nex[i])
- if(col[u]!=col[_v[i]]) rd[col[_v[i]]]++;
- for(int i=1; i<=sumcol; ++i) cnt+=(!rd[i]);
- for(int u=1; u<=n; ++u)
- {
- if(rd[col[u]]||point[col[u]]>1) continue;
- for(int i=head[u]; i; i=_nex[i])
- if(rd[col[_v[i]]]<2) goto next_;
- cnt--; break; next_:;
- }
- printf("%.6lf\n",1*1.-1.*cnt/n);
- return 0;
- }
- int Aptal=Presist();
- int main(int argc,char**argv){;}
BZOJ——2438: [中山市选2011]杀人游戏
来源: http://www.bubuko.com/infodetail-2400618.html