标签:分享 识别 kill 存在 i++ stack ace ring stdin
题目
一位冷血的杀手潜入 Na-wiat,并假装成平民。警察希望能在 N 个人里面,查出谁是杀手。警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人,谁是杀手,谁是平民。假如查证的对象是杀手,杀手将会把警察干掉。现在警察掌握了每一个人认识谁。每一个人都有可能是杀手,可看作他们是杀手的概率是相同的。问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少?INPUT
第一行有两个整数 N,M。接下来有 M 行,每行两个整数 x,y,表示 x 认识 y(y 不一定认识 x)。OUTPUT
仅包含一行一个实数,保留小数点后面 6 位,表示最大概率。SAMPLE
INPUT
5 41 21 31 41 5OUTPUT
0.800000
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 inline int read(){ 6 int sum(0); 7 char ch(getchar()); 8 for(;ch<‘0‘||ch>‘9‘;ch=getchar()); 9 for(;ch>=‘0‘&&ch<=‘9‘;sum=sum*10+(ch^48),ch=getchar()); 10 return sum; 11 } 12 struct edge{ 13 int s,e,n; 14 }a[300001],b[100001]; 15 int pre[100001],tot; 16 int adj[100001],ttt; 17 inline void insert(int s,int e){ 18 a[++tot].s=s; 19 a[tot].e=e; 20 a[tot].n=pre[s]; 21 pre[s]=tot; 22 } 23 inline void add(int s,int e){ 24 b[++ttt].s=s; 25 b[ttt].e=e; 26 b[ttt].n=adj[s]; 27 adj[s]=ttt; 28 } 29 int n,m; 30 int stack[100001],top; 31 int cnt,low[100001],dfn[100001],bl[100001],qlt; 32 bool vis[100001]; 33 int size[100001]; 34 inline int my_min(int a,int b){ 35 return a<b?a:b; 36 } 37 inline void tarjan(int u){ 38 cnt++; 39 vis[u]=1; 40 low[u]=dfn[u]=cnt; 41 stack[++top]=u; 42 for(int i=pre[u];i!=-1;i=a[i].n){ 43 int e(a[i].e); 44 if(!dfn[e]){ 45 tarjan(e); 46 low[u]=my_min(low[u],low[e]); 47 } 48 else 49 if(vis[e]) 50 low[u]=my_min(low[u],dfn[e]); 51 } 52 if(low[u]==dfn[u]){ 53 int tmp; 54 qlt++; 55 while(1){ 56 tmp=stack[top--]; 57 bl[tmp]=qlt; 58 vis[tmp]=0; 59 if(tmp==u) 60 break; 61 } 62 } 63 } 64 bool flag[100001]; 65 inline void uni(int u){//坑点处理dfs 66 for(int i=adj[u];i!=-1;i=b[i].n){ 67 int e(b[i].e); 68 if(!vis[e]){ 69 vis[e]=1; 70 uni(e); 71 size[u]+=size[e]; 72 } 73 } 74 } 75 int ans(0); 76 int ind[100001]; 77 int main(){ 78 // freopen("killer.in","r",stdin); 79 // freopen("killer.out","w",stdout); 80 memset(pre,-1,sizeof(pre)); 81 memset(adj,-1,sizeof(adj)); 82 n=read(),m=read(); 83 for(int i=1;i<=m;i++){ 84 int x(read()),y(read()); 85 insert(x,y); 86 } 87 for(int i=1;i<=n;i++) 88 if(!dfn[i]) 89 tarjan(i); 90 for(int i=1;i<=n;i++) 91 size[bl[i]]++; 92 for(int i=1;i<=m;i++){ 93 int s(a[i].s),e(a[i].e); 94 if(bl[s]!=bl[e]) 95 add(bl[s],bl[e]),ind[bl[e]]++; 96 } 97 for(int i=1;i<=qlt;i++) 98 if(!ind[i]){//坑点特判 99 uni(i); 100 if(size[i]==1){ 101 ans=-1; 102 break; 103 } 104 } 105 for(int i=1;i<=qlt;i++) 106 if(ind[i]==0) 107 ans++; 108 printf("%.6lf",(double)(n-ans)/(double)n); 109 }
标签:分享 识别 kill 存在 i++ stack ace ring stdin
原文地址:http://www.cnblogs.com/hzoi-mafia/p/7276887.html