【BZOJ2438】 [中山市选2011]杀人游戏 tarjan强连通分量+缩点

Description

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

Input

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

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


数据已加强!

tarjan求强连通+缩点后,统计入度为0的点,最后特判一下(并不知道为什么)。
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <queue>
  6 #include <stack>
  7 #define N 500500
  8 #define M 500500
  9 using namespace std;
 10 struct data{int next,p;}e1[M],e2[M];
 11 int head1[N],head2[N],belong[N],low[N],dfn[N],mon[N],vscc[N],dis[N],inq[N],vis[N];
 12 int q1[N],q[N];
 13 int n,m,S,p,cnt,ans,qt,scc;
 14 inline int max(int x,int y){return x>y?x:y;}
 15 inline int min(int x,int y){return x<y?x:y;}
 16 inline int read()
 17 {
 18     char c;
 19     int anss=0;
 20     while ((c=getchar())==' ' || c=='\n' || c=='\r');
 21     anss=c-'0';
 22     while (isdigit(c=getchar())) anss=anss*10+c-'0';
 23     return anss;
 24 }
 25 void se1(int x,int y){cnt++; e1[cnt].next=head1[x]; head1[x]=cnt; e1[cnt].p=y;}
 26 void se2(int x,int y){cnt++; e2[cnt].next=head2[x]; head2[x]=cnt; e2[cnt].p=y;}
 27 void tarjan(int x)
 28 {
 29     vis[x]=inq[x]=1;
 30     dfn[x]=low[x]=++cnt;
 31     q1[++qt]=x;
 32     for (int i=head1[x];i;i=e1[i].next)//i全打成xSB调了好久。 
 33     {
 34         if (!vis[e1[i].p])
 35         {
 36             tarjan(e1[i].p);
 37             low[x]=min(low[x],low[e1[i].p]);
 38         }
 39         else if (inq[e1[i].p])    low[x]=min(low[x],low[e1[i].p]);
 40     }
 41     if (low[x]==dfn[x])
 42     {
 43         int now=0;
 44         scc++;
 45         while (now!=x)
 46         {
 47             now=q1[qt];qt--;
 48             belong[now]=scc;
 49             inq[now]=0;
 50             vscc[scc]+=mon[now];
 51         }
 52     }
 53 }
 54 void part1_tarjan()
 55 {
 56     cnt=0;
 57     for (int i=1;i<=n;i++)
 58         if (!vis[i])    tarjan(i);
 59 }
 60 void part2_shr_point()
 61 {
 62     cnt=0;
 63     for (int i=1;i<=n;i++)
 64         for (int j=head1[i];j;j=e1[j].next)
 65             if (belong[i]!=belong[e1[j].p])
 66                 se2(belong[i],belong[e1[j].p]);
 67 }
 68 void part3_spfa()
 69 {
 70     memset(inq,0,sizeof(inq));
 71     int t=0,w=1;
 72     q[t]=belong[S];
 73     inq[belong[S]]=1;
 74     dis[belong[S]]=vscc[belong[S]];
 75     while  (t!=w)
 76     {
 77         int now=q[t];t++;
 78         for (int i=head2[now];i;i=e2[i].next)
 79             if (dis[e2[i].p]<dis[now]+vscc[e2[i].p])
 80             {
 81                 dis[e2[i].p]=dis[now]+vscc[e2[i].p];
 82                 if (!inq[e2[i].p])
 83                 {
 84                     inq[e2[i].p]=1;
 85                     q[w++]=e2[i].p;
 86                 }
 87             }
 88         inq[now]=0;
 89     }
 90 }
 91 int main()
 92 {
 93     n=read();m=read();
 94     for (int i=1;i<=m;i++)    
 95     {
 96         int x,y;
 97         x=read();y=read();
 98         se1(x,y);
 99     }
100     for (int i=1;i<=n;i++)    mon[i]=read();
101     part1_tarjan();
102     part2_shr_point();
103     S=read();p=read();
104     part3_spfa();
105     for (int i=1;i<=p;i++)
106     {
107         int x=read();
108         if (dis[belong[x]]>ans) ans=dis[belong[x]];
109     }
110     printf("%d\n",ans);
111     return 0;
112 }
View Code

 

posted @ 2016-03-08 19:04  DMoon  阅读(177)  评论(0编辑  收藏  举报