1. 程式人生 > >BZOJ1415: [Noi2005]聰聰和可可

BZOJ1415: [Noi2005]聰聰和可可

align 這不 概率 包含 text set bzoj void ica

題目描述

在一個魔法森林裏,住著一只聰明的小貓聰聰和一只可愛的小老鼠可可。雖 然灰姑娘非常喜歡她們倆,但是,聰聰終究是一只貓,而可可終究是一只老鼠, 同樣不變的是,聰聰成天想著要吃掉可可。

一天,聰聰意外得到了一臺非常有用的機器,據說是叫 GPS,對可可能準確 的定位。有了這臺機器,聰聰要吃可可就易如反掌了。於是,聰聰準備馬上出發, 去找可可。而可憐的可可還不知道大難即將臨頭,仍在森林裏無憂無慮的玩耍。 小兔子乖乖聽到這件事,馬上向灰姑娘報告。灰姑娘決定盡快阻止聰聰,拯救可 可,可她不知道還有沒有足夠的時間。

整個森林可以認為是一個無向圖,圖中有 NNN 個美麗的景點,景點從 111 至 NNN 編號。小動物們都只在景點休息、玩耍。在景點之間有一些路連接。

當聰聰得到 GPS 時,可可正在景點 MMM(M≤NM≤NMN)處。以後的每個時間單位,可可 都會選擇去相鄰的景點(可能有多個)中的一個或停留在原景點不動。而去這些地方所發生的概率是相等的。假設有 PPP 個景點與景點 M 相鄰,它們分別是景點 R、 景點 S,……景點 Q,在時刻 TTT 可可處在景點 M,則在( T+1 T+1 T+1 )時刻,可可有 1/(1+P)1/(1 +P)1/(1+P) 的可能在景點 R,有 1/(1+P)1/(1 +P)1/(1+P) 的可能在景點 S,……,有 1/(1+P)1/(1 +P)1/(1+P) 的可能在景點 Q

,還有1/(1+P)1/(1 +P)1/(1+P)的可能停在景點 M

我們知道,聰聰是很聰明的,所以,當她在景點 C 時,她會選一個更靠近 可可的景點,如果這樣的景點有多個,她會選一個標號最小的景點。由於聰聰太 想吃掉可可了,如果走完第一步以後仍然沒吃到可可,她還可以在本段時間內再 向可可走近一步。

在每個時間單位,假設聰聰先走,可可後走。在某一時刻,若聰聰和可可位 於同一個景點,則可憐的可可就被吃掉了。

灰姑娘想知道,平均情況下,聰聰幾步就可能吃到可可。而你需要幫助灰姑 娘盡快的找到答案。

輸入輸出格式

輸入格式:

數據的第 1 行為兩個整數 NNN 和 EEE,以空格分隔,分別表示森林中的景點數和 連接相鄰景點的路的條數。

第 2 行包含兩個整數 CCC 和 MMM,以空格分隔,分別表示初始時聰聰和可可所在的景點的編號。

接下來 E 行,每行兩個整數,第 i+2i+2i+2 行的兩個整數 AiA_iAi?BiB_iBi?表示景點 AiA_iAi?和景點 BiB_iBi? 之間有一條路。 所有的路都是無向的,即:如果能從 A 走到 B,就可以從 B 走到 A。

輸入保證任何兩個景點之間不會有多於一條路直接相連,且聰聰和可可之間必有路直接或間接的相連。

輸出格式:

輸出 1 個實數,四舍五入保留三位小數,表示平均多少個時間單位後聰聰會把可可吃掉。

【輸入樣例1】
4 3
1 4
1 2
2 3
3 4
【輸入樣例2】
9 9
9 3
1 2
2 3
3 4
4 5
3 6
4 6
4 7
7 8
8 9

【輸出樣例1】
1.500
【輸出樣例2】
2.167

解題思路:

本來算了一下時間,應該是一個遍歷的復雜度,大概是可以忍受的,即使再差,最差也是配對的時間復雜度。

然後卡在了建圖。

floyd穩定O(n3)想都不用想。

然後我就被卡死了。

回頭再看一下數據範圍,點數邊數很接近誒。

據說Spfa處理稀疏圖有奇效。不過Spfa不是死了嗎。

這不是05年嘛。

代碼:

  1 #include<queue>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 struct pnt{
  6     int hd;
  7     int no;
  8     double dp[1001];
  9     double num;
 10     int dis[1001];
 11     int nxt[1001];
 12     bool hvn[1001];
 13     bool in;
 14     bool vis[1001];
 15 }p[1001];
 16 struct ent{
 17     int twd;
 18     int lst;
 19 }e[100000];
 20 int n,m;
 21 int cnt;
 22 int cc,kk;
 23 std::queue<int>Q;
 24 void ade(int f,int t)
 25 {
 26     cnt++;
 27     e[cnt].twd=t;
 28     e[cnt].lst=p[f].hd;
 29     p[f].hd=cnt;
 30     return ;
 31 }
 32 void Spfa(int x)
 33 {
 34     for(int i=1;i<=n;i++)
 35     {
 36         p[i].in=0;
 37         p[x].dis[i]=0x3f3f3f3f;
 38         p[x].nxt[i]=0x3f3f3f3f;
 39     }
 40     p[x].dis[x]=0;
 41     p[x].in=1;
 42     Q.push(x);
 43     while(!Q.empty())
 44     {
 45         int s=Q.front();
 46         Q.pop();
 47         p[s].in=false;
 48         for(int i=p[s].hd;i;i=e[i].lst)
 49         {
 50             int to=e[i].twd;
 51             if(p[x].dis[to]>p[x].dis[s]+1)
 52             {
 53                 p[x].dis[to]=p[x].dis[s]+1;
 54                 if(!p[to].in)
 55                     Q.push(to);
 56                 p[to].in=true;
 57             }
 58         }
 59     }
 60     return ;
 61 }
 62 double Dp(int killer,int deserter)
 63 {
 64     if(p[killer].vis[deserter])
 65         return p[killer].dp[deserter];
 66     if(deserter==killer)
 67     {
 68         p[killer].dp[deserter]=0.00;
 69         p[killer].dp[deserter]=true;
 70         return 0.00;
 71     }
 72     int kl=killer;
 73     killer=p[killer].nxt[deserter];
 74     if(killer==deserter)
 75         return 1.00;
 76     killer=p[killer].nxt[deserter];
 77     if(killer==deserter)
 78         return 1.00;
 79     p[kl].dp[deserter]=(1.00/p[deserter].num)*(1.00+Dp(killer,deserter));
 80     for(int i=p[deserter].hd;i;i=e[i].lst)
 81     {
 82         int to=e[i].twd;
 83         p[kl].dp[deserter]+=(1.00/p[deserter].num)*(1.00+Dp(killer,to));
 84     }
 85     
 86     p[kl].vis[deserter]=true;
 87     return p[kl].dp[deserter];
 88 }
 89 int main()
 90 {
 91     scanf("%d%d%d%d",&n,&m,&cc,&kk);
 92     for(int i=1;i<=n;i++)
 93     {
 94         p[i].no=i;
 95         p[i].num=1.00;
 96     }
 97     for(int i=1;i<=m;i++)
 98     {
 99         int a,b;
100         scanf("%d%d",&a,&b);
101         p[a].dp[b]=p[b].dp[a]=1.00;
102         p[a].vis[b]=p[b].vis[a]=true;
103         ade(a,b);
104         ade(b,a);
105         p[a].num+=1.00;
106         p[b].num+=1.00;
107     }
108     for(int i=1;i<=n;i++)
109         Spfa(i);
110     for(int x=1;x<=n;x++)
111         for(int i=p[x].hd;i;i=e[i].lst)
112         {
113             int to=e[i].twd;
114             for(int j=1;j<=n;j++)
115                 if(p[to].dis[j]+1==p[x].dis[j])
116                     p[x].nxt[j]=std::min(to,p[x].nxt[j]);
117         }
118     printf("%.3lf\n",Dp(cc,kk));
119     return 0;
120 }

BZOJ1415: [Noi2005]聰聰和可可