BZOJ1415: [Noi2005]聰聰和可可
題目描述
在一個魔法森林裏,住著一只聰明的小貓聰聰和一只可愛的小老鼠可可。雖 然灰姑娘非常喜歡她們倆,但是,聰聰終究是一只貓,而可可終究是一只老鼠, 同樣不變的是,聰聰成天想著要吃掉可可。
一天,聰聰意外得到了一臺非常有用的機器,據說是叫 GPS,對可可能準確 的定位。有了這臺機器,聰聰要吃可可就易如反掌了。於是,聰聰準備馬上出發, 去找可可。而可憐的可可還不知道大難即將臨頭,仍在森林裏無憂無慮的玩耍。 小兔子乖乖聽到這件事,馬上向灰姑娘報告。灰姑娘決定盡快阻止聰聰,拯救可 可,可她不知道還有沒有足夠的時間。
整個森林可以認為是一個無向圖,圖中有 NNN 個美麗的景點,景點從 111 至 NNN 編號。小動物們都只在景點休息、玩耍。在景點之間有一些路連接。
當聰聰得到 GPS 時,可可正在景點 MMM(M≤NM≤NM≤N)處。以後的每個時間單位,可可 都會選擇去相鄰的景點(可能有多個)中的一個或停留在原景點不動。而去這些地方所發生的概率是相等的。假設有 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
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]聰聰和可可