1. 程式人生 > >bzoj1778

bzoj1778

size rda names 成了 1.0 mes include lap jordan

高斯消元+矩陣的逆

來自popoqqq大神

技術分享

求矩陣的逆:把I-T放在左邊,P/Q*S放在右邊,這樣就形成了一個n*2n的矩陣,然後把左邊高斯消元,右邊就是求完逆的矩陣,其實就是ans,矩陣的逆跟乘法逆元是一樣的,只不過是矩陣的逆元

然後輸出a[i][n+1],事實上矩陣只有n*(n+1)

構造轉移概率矩陣是a[u][v]=1.0/d[v]*(1-p/q),就是v->u的概率乘上在v不爆炸的概率

技術分享
#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-15;
const int N = 610;
int n, m;
double a[N][N]; double p, q, t; vector<int> G[N]; void gauss_jordan() { a[1][n + 1] = t; for(int i = 1; i <= n; ++i) { a[i][i] += 1.0; for(int j = 0; j < G[i].size(); ++j) { int u = G[i][j]; a[i][u] -= (1.0 - t) / (double)(G[u].size()); } }
for(int now = 1; now <= n; ++now) { int x = now; for(int i = now; i <= n; ++i) if(fabs(a[i][now]) > fabs(a[x][now])) x = i; for(int i = 1; i <= n + 1; ++i) swap(a[now][i], a[x][i]); double t = a[now][now]; for(int i = 1; i <= n + 1; ++i) a[now][i] /= t;
for(int i = 1; i <= n; ++i) if(fabs(a[i][now]) > eps && now != i) { t = a[i][now]; for(int j = 1; j <= n + 1; ++j) a[i][j] -= t * a[now][j]; } } for(int i = 1; i <= n; ++i) printf("%.9f\n", a[i][n + 1]); } int main() { scanf("%d%d%lf%lf", &n, &m, &p, &q); t = p / q; for(int i = 1; i <= m; ++i) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } gauss_jordan(); return 0; }
View Code

bzoj1778