洛谷P4206 聪聪与可可
无向简单图上给定s,t。每秒s先向t按照最短路走两步(优先节点编号较小的),然后t随机行动一步。
问期望多少秒相遇。n <= 1000
解:
这个s太蛇皮了...所以预处理一波。
然后不会,看题解发现是SB记忆化搜索......
1 #include <bits/stdc++.h> 2 3 const int N = 1010; 4 const double eps = 1e-13; 5 6 struct Edge { 7 int nex, v; 8 }edge[N << 1]; int tp; 9 10 int e[N], gt[N][N], n, m, fr[N], d[N], vis[N], in[N], frfr[N]; 11 double f[N][N]; 12 std::queue<int> Q; 13 14 inline void add(int x, int y) { 15 tp++; 16 edge[tp].v = y; 17 edge[tp].nex = e[x]; 18 e[x] = tp; 19 return; 20 } 21 22 void DFS(int x, int s) { 23 for(int i = e[x]; i; i = edge[i].nex) { 24 int y = edge[i].v; 25 if(fr[y] == x) { 26 gt[s][y] = gt[s][x]; 27 DFS(y, s); 28 } 29 } 30 return; 31 } 32 33 inline void BFS(int s) { 34 Q.push(s); 35 vis[s] = s; 36 d[s] = 0; 37 fr[s] = 0; frfr[s] = 0; 38 while(Q.size()) { 39 int x = Q.front(); 40 Q.pop(); 41 for(int i = e[x]; i; i = edge[i].nex) { 42 int y = edge[i].v; 43 if(vis[y] != s) { 44 vis[y] = s; 45 d[y] = d[x] + 1; 46 fr[y] = x; 47 frfr[y] = (x == s) ? y : frfr[x]; 48 Q.push(y); 49 } 50 else if(d[y] == d[x] + 1) { 51 if(frfr[x] < frfr[y]) { 52 frfr[y] = frfr[x]; 53 fr[y] = x; 54 } 55 } 56 } 57 } 58 /// get gt 59 gt[s][s] = s; f[s][s] = 0; 60 for(int i = e[s]; i; i = edge[i].nex) { 61 int y = edge[i].v; 62 gt[s][y] = y; 63 DFS(y, s); 64 } 65 return; 66 } 67 68 double F(int x, int y) { 69 if(f[x][y] >= -eps) { 70 return f[x][y]; 71 } 72 if(gt[x][y] == y || gt[gt[x][y]][y] == y) { 73 return f[x][y] = 1; 74 } 75 double ans = 0; 76 77 int z = gt[gt[x][y]][y]; 78 for(int i = e[y]; i; i = edge[i].nex) { 79 int w = edge[i].v; 80 ans += F(z, w); 81 } 82 ans += F(z, y); 83 84 return f[x][y] = ans / (in[y] + 1) + 1; 85 } 86 87 int main() { 88 int s, t; 89 scanf("%d%d", &n, &m); 90 scanf("%d%d", &s, &t); 91 for(int i = 1, x, y; i <= m; i++) { 92 scanf("%d%d", &x, &y); 93 add(x, y); add(y, x); 94 in[x]++; in[y]++; 95 } 96 97 for(int i = 1; i <= n; i++) { 98 for(int j = 1; j <= n; j++) { 99 f[i][j] = -1; 100 } 101 } 102 103 for(int i = 1; i <= n; i++) { 104 BFS(i); 105 } 106 107 /*printf("-----------\n"); 108 for(int i = 1; i <= n; i++) { 109 for(int j = 1; j <= n; j++) { 110 printf("%d ", gt[i][j]); 111 } 112 printf("\n"); 113 } 114 printf("-----------\n"); 115 */ 116 117 printf("%.3f\n", F(s, t)); 118 return 0; 119 }
感觉不会死循环的原因是每次之后s和t的距离至少减少1,至多减少3。按s和t的距离分层的话每一步都走到了不同的层。