大意:給定簡單無向圖,從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 }