bzoj2438: [中山市選2011]殺人遊戲(強聯通+特判)

來源:互聯網
上載者:User

標籤:矛盾   一個人   san   接下來   選擇   ems   成功   直接   memset   

2438: [中山市選2011]殺人遊戲

題目:傳送門 

簡要題意:

   給出n個點,m條有向邊,進行最少的訪問並且可以便利(n-1)個點,求這個方案成功的機率

題解:
   一道非常好的題目!

   題目要知道最大的存活機率,那麼也就是找到直接找到殺手的最小機率

   那麼我們採用強聯通縮點:

   統計每個聯通分量的入度,如果入度為0(證明除此聯通分量裡的點,沒有人可以知道連通分量裡的資訊,那就一定要先選一個人訪問),那麼sum++(因為依據題意,假如問到連通分量裡的任意一個人,只要ta不是殺手,那麼一定可以安全的遍曆強聯通分量裡的所有人)

   接下來就是最關鍵的特判:

   對於連通分量裡只有一個點的情況,如果它的入度為零,不一定就要訪問(這裡何前面似乎有些許矛盾)

   解釋:如果有聯通分量只有一個家族成員,並且沒有入度,因為殺手只有一個,那麼我們完全可以在遍曆其他的n-1個點時得出答案(排除法嘛)

   但是它的出度不一定為0,所以還要判斷一下在上面的基礎上,這個點連出去的邊是否能夠被其他點訪問(入度>1),很好理解吧

   如果以上的都滿足,那麼sum--

   還有一個小槽點:sum--一次就好了,因為如果有兩種相同的情況,那麼對於兩個獨立的點,我們還是要選擇一個訪問才能遍曆完成的

   輸出1.0-double(sum)/double(n)

代碼:

  1 #include<cstdio>  2 #include<cstring>  3 #include<cstdlib>  4 #include<cmath>  5 #include<algorithm>  6 using namespace std;  7 int n,m;  8 struct node  9 { 10     int x,y,next; 11 }a[1110000];int len,last[510000]; 12 void ins(int x,int y) 13 { 14     len++; 15     a[len].x=x;a[len].y=y; 16     a[len].next=last[x];last[x]=len; 17 } 18 struct edge 19 { 20     int x,y,next; 21 }e[1110000];int len1,last1[510000]; 22 void inss(int x,int y) 23 { 24     len1++; 25     e[len1].x=x;e[len1].y=y; 26     e[len1].next=last1[x];last1[x]=len1; 27 } 28 int cnt,tp,id; 29 int belong[510000],dfn[510000],low[510000],sta[510000],size[510000]; 30 bool v[510000]; 31 void dfs(int x) 32 { 33     low[x]=dfn[x]=++id; 34     sta[++tp]=x;v[x]=true; 35     for(int k=last[x];k;k=a[k].next) 36     { 37         int y=a[k].y; 38         if(dfn[y]==-1) 39         { 40             dfs(y); 41             low[x]=min(low[x],low[y]); 42         } 43         else 44         { 45             if(v[y]==true) 46                 low[x]=min(low[x],dfn[y]); 47         } 48     } 49     if(low[x]==dfn[x]) 50     { 51         int i;cnt++; 52         do{ 53             i=sta[tp--]; 54             v[i]=false; 55             belong[i]=cnt; 56             size[cnt]++; 57         }while(i!=x); 58     } 59 } 60 int ru[510000],chu[510000],sum1,sum2; 61 bool check(int x) 62 { 63     if(size[x]!=1)return true; 64     if(last1[x]==0)return false; 65     for(int k=last1[x];k;k=e[k].next) 66     { 67         int y=e[k].y; 68         if(ru[y]<=1)return true; 69     } 70     return false; 71 } 72 int main() 73 { 74     cnt=tp=id=sum1=sum2=0; 75     len=0;len1=0; 76     memset(last,0,sizeof(last));memset(last1,0,sizeof(last1)); 77     scanf("%d%d",&n,&m); 78     memset(chu,0,sizeof(chu)); 79     memset(ru,0,sizeof(ru)); 80     memset(sta,0,sizeof(sta)); 81     memset(dfn,-1,sizeof(dfn)); 82     memset(low,0,sizeof(low)); 83     memset(v,false,sizeof(v)); 84     for(int i=1;i<=m;i++) 85     { 86         int x,y; 87         scanf("%d%d",&x,&y); 88         ins(x,y); 89     } 90     for(int i=1;i<=n;i++) 91         if(dfn[i]==-1) 92             dfs(i); 93     for(int i=1;i<=m;i++) 94     { 95         int st=belong[a[i].x],ed=belong[a[i].y]; 96         if(st!=ed) 97         { 98             ru[ed]++; 99             inss(st,ed);100         }101     }102     for(int i=1;i<=cnt;i++)103         if(ru[i]==0)sum1++;104     for(int i=1;i<=cnt;i++)105         if(ru[i]==0)106             if(check(i)==false){sum1--;break;}107     printf("%.6lf\n",1.0-double(sum1)/double(n));108     return 0;109 }

 

bzoj2438: [中山市選2011]殺人遊戲(強聯通+特判)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.