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
,还有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 个实数,四舍五入保留三位小数,表示平均多少个时间单位后聪聪会把可可吃掉。
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 }