[HNOI2013]遊走

大意:給定簡單無向圖,從1號點出發,等機率走路,到n號點中止。ide

求每條邊通過的次數指望。spa

解:code

邊的指望能夠由點的機率很容易推出來。blog

點的機率是互相關聯的,好比1號一開始機率爲1,可是可能出去以後就回來結果機率比1還大了,而後又會影響到別的點....it

有一種高斯消元的感受,再一看數據範圍:恰好!那麼就是你了!io

每一個點的機率應該是從全部邊過來的機率之和。event

注意:常數項全0是解不了的。可是咱們的一號點有個常數項爲1class

爲何有個負號呢?cli

由於把a[1][1]*f[1]移過去以後恰好是f[1] - 1,這就沒問題了。sed

其他的貢獻加起來再加原來就有的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代碼
相關文章
相關標籤/搜索