洛谷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 }
AC代码

感觉不会死循环的原因是每次之后s和t的距离至少减少1,至多减少3。按s和t的距离分层的话每一步都走到了不同的层。

posted @ 2019-03-24 22:03  huyufeifei  阅读(226)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜