• [HNOI2013]游走


    大意:给定简单无向图,从1号点出发,等概率走路,到n号点停止。

    求每条边经过的次数期望。

    解:

    边的期望可以由点的概率很容易推出来。

    点的概率是互相关联的,比如1号一开始概率为1,但是可能出去之后就回来结果概率比1还大了,然后又会影响到别的点....

    有一种高斯消元的感觉,再一看数据范围:刚好!那么就是你了!

    每个点的概率应该是从所有边过来的概率之和。

    注意:常数项全0是解不了的。但是我们的一号点有个常数项为1

    为什么有个负号呢?

    因为把a[1][1]*f[1]移过去之后刚好是f[1] - 1,这就没问题了。

    其余的贡献加起来再加原来就有的1就是f[1]

    n号点不能为其他任一点的概率做贡献。

    然后我们就可以列方程,解方程,然后搞出答案了。

    精度开到1e12,否则可能WA

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cmath>
      4 const int N = 510;
      5 const double eps = 1e-12;
      6 
      7 struct Edge {
      8     int v, nex;
      9 }edge[N * N * 2]; int top = 1;
     10 
     11 int e[N], out[N], n, m, t;
     12 double a[N][N], f[N], b[N * N];
     13 
     14 inline void add(int x, int y) {
     15     top++;
     16     edge[top].v = y;
     17     edge[top].nex = e[x];
     18     e[x] = top;
     19     out[x]++;
     20     return;
     21 }
     22 
     23 inline void Gauss() {
     24     for(int i = 1; i < n; i++) {
     25         for(int j = i; j <= n; j++) {
     26             if(fabs(a[j][i]) > eps) {
     27                 std::swap(a[j], a[i]);
     28                 break;
     29             }
     30         }
     31         for(int j = i + 1; j <= n; j++) {
     32             if(fabs(a[j][i]) < eps) {
     33                 continue;
     34             }
     35             double p = a[j][i] / a[i][i];
     36             for(int k = i; k <= n + 1; k++) {
     37                 a[j][k] -= a[i][k] * p;
     38             }
     39         }
     40     }
     41 
     42     for(int i = n; i > 1; i--) {
     43         for(int j = i - 1; j >= 1; j--) {
     44             if(fabs(a[j][i]) < eps) {
     45                 continue;
     46             }
     47             double p = a[j][i] / a[i][i];
     48             for(int k = i; k <= n + 1; k++) {
     49                 a[j][k] -= a[i][k] * p;
     50             }
     51         }
     52     }
     53 
     54     for(int i = 1; i <= n; i++) {
     55         f[i] = a[i][n + 1] / a[i][i];
     56     }
     57 
     58     return;
     59 }
     60 
     61 int main() {
     62     scanf("%d%d", &n, &m);
     63     for(int i = 1, x, y; i <= m; i++) {
     64         scanf("%d%d", &x, &y);
     65         add(x, y);
     66         add(y, x);
     67     }
     68     out[n] = 0;
     69 
     70     for(int x = 1; x < n; x++) {
     71         for(int i = e[x]; i; i = edge[i].nex) {
     72             int y = edge[i].v;
     73             a[y][x] = 1.0 / out[x];
     74         }
     75         a[x][x] = -1.0;
     76     }
     77     a[1][n + 1] = -1.0;
     78     a[n][n] = -1.0;
     79 
     80     Gauss();
     81 
     82     for(int i = 2; i <= top; i += 2) {
     83         ++t;
     84         if(edge[i].v < n) {
     85             b[t] = f[edge[i].v] / out[edge[i].v];
     86         }
     87         if(edge[i ^ 1].v < n) {
     88             b[t] += f[edge[i ^ 1].v] / out[edge[i ^ 1].v];
     89         }
     90     }
     91 
     92     std::sort(b + 1, b + t + 1);
     93 
     94     double ans = 0;
     95     for(int i = t; i >= 1; i--) {
     96         ans += b[i] * (t + 1 - i);
     97     }
     98 
     99     printf("%.3lf", ans);
    100 
    101     return 0;
    102 }
    AC代码
  • 相关阅读:
    CentOS 阿里源
    使用分区挂载 ftp 目录
    Docker-compose常用命令
    docker 启动容器失败 id already in use
    Docker daemon.json 的配置项目合集
    Watchtower
    umount 时目标忙解决办法
    opencontrail 参考资料
    使用disk-image-builder(DIB)制作Ironic 裸金属镜像
    Nodejs常见安装
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9414869.html
Copyright © 2020-2023  润新知