首先我们列出转移矩阵$M$,$M_{i, j} = \frac {1 - \frac{p} {q}} {deg[i]}$(i,j之间有边)or $M_{i, j} = 0$(i,j之间没边)
则这个矩阵$M_{i, j}$表示的是站在某个点$i$,下一次走到$j$且没有爆炸的概率
我们再看$M^n_{i, j}$,表示的站在某个点$i$,走$n$步以后到达$j$且没有爆炸的概率
故$M^n$的第一列代表了$1$号点到其他所有点的概率,设为列向量$A_n$,则$A_n = M^n * B$,其中$B = (1, 0, 0, 0, ...)^T$
设第n步到各点且爆炸了的概率的列向量为$P_n$,则$P_n = \frac{p} {q} * A_n$
故答案列向量$Ans = \sum_{i = 0} ^ {+\infty} P_i$
把它展开:$Ans = \frac{p} {q} * (\sum_{i = 0} ^ {+\infty} M^i) * B$
由等比数列求和公式,$\sum_{i = 0} ^ {+\infty} M^i = \frac{I} {I - M} = (I - M)^{-1}$
故$Ans = \frac{p} {q} * (I - M)^{-1} * B$,即$(I- M) * Ans = \frac{p} {q} * B$
得到一个线性方程组,我们只要高斯消元即可
1 /************************************************************** 2 Problem: 1778 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:200 ms 7 Memory:2264 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cmath> 12 #include <algorithm> 13 14 using namespace std; 15 typedef double lf; 16 const int N = 305; 17 const int M = N * N; 18 19 inline int read(); 20 21 struct edge { 22 int next, to; 23 edge() {} 24 edge(int _n, int _t) : next(_n), to(_t) {} 25 } e[M]; 26 27 int n, m, deg[N]; 28 int first[N], tot; 29 lf P, a[N][N], ans[N]; 30 31 inline void Add_Edges(int x, int y) { 32 e[++tot] = edge(first[x], y), first[x] = tot; 33 e[++tot] = edge(first[y], x), first[y] = tot; 34 ++deg[x], ++deg[y]; 35 } 36 37 #define y e[x].to 38 inline void build_matrix() { 39 int p, x; 40 for (p = 1; p <= n; ++p) { 41 for (x = first[p]; x; x = e[x].next) 42 a[p][y] = -(1.0 - P) / deg[y]; 43 a[p][p] = 1; 44 } 45 a[1][n + 1] = P; 46 } 47 #undef y 48 49 void gauss(int n) { 50 int i, j, k; 51 lf tmp; 52 for (i = 1; i <= n; ++i) { 53 for (k = i, j = i + 1; j <= n; ++j) 54 if (fabs(a[j][i]) > fabs(a[k][i])) k = j; 55 for (j = i; j <= n + 1; ++j) swap(a[i][j], a[k][j]); 56 for (k = i + 1; k <= n; ++k) 57 for (tmp = -a[k][i] / a[i][i], j = i; j <= n + 1; ++j) 58 a[k][j] += a[i][j] * tmp; 59 } 60 for (i = n; i; --i) { 61 for (j = i + 1; j <= n; ++j) 62 a[i][n + 1] -= a[i][j] * ans[j]; 63 ans[i] = a[i][n + 1] / a[i][i]; 64 } 65 } 66 67 int main() { 68 int i, j; 69 n = read(), m = read(), P = 1.0 * read() / read(); 70 for (i = 1; i <= m; ++i) 71 Add_Edges(read(), read()); 72 build_matrix(); 73 gauss(n); 74 for (i = 1; i <= n; ++i) 75 printf("%.9lf\n", ans[i]); 76 return 0; 77 } 78 79 inline int read() { 80 static int x; 81 static char ch; 82 x = 0, ch = getchar(); 83 while (ch < '0' || '9' < ch) 84 ch = getchar(); 85 while ('0' <= ch && ch <= '9') { 86 x = x * 10 + ch - '0'; 87 ch = getchar(); 88 } 89 return x; 90 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen