bzoj 3270 博物馆 高斯消元
题面
解法
设\((x,y)\)表示第一个人在\(x\)房间,第二个人在\(y\)房间,然后列一个方程组即可
直接用高斯消元解一下就行了
时间复杂度:\(O(n^6)\)
代码
#include <bits/stdc++.h>
#define double long double
#define eps 1e-9
#define N 410
using namespace std;
int n, m, cnt, s[N], f[N][N];
double p[N], a[N][N];
int calc(int x, int y) {return (x - 1) * n + y;}
void gauss(int n) {
for (int i = 1; i <= n; i++) {
if (fabs(a[i][i]) < eps)
for (int j = i + 1; j <= n; j++)
if (fabs(a[j][i]) > eps)
for (int k = 1; k <= n + 1; k++) swap(a[i][k], a[j][k]);
for (int j = i + 1; j <= n + 1; j++) a[i][j] /= a[i][i];
for (int j = 1; j <= n; j++) {
if (i == j) continue;
for (int k = i + 1; k <= n + 1; k++)
a[j][k] -= a[j][i] * a[i][k];
}
}
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m; int sx, sy;
cin >> sx >> sy; cnt = n;
for (int i = 1; i <= m; i++) {
int x, y; cin >> x >> y;
f[x][y] = f[y][x] = 1;
s[x]++, s[y]++;
}
a[calc(sx, sy)][n * n + 1] = 1;
for (int i = 1; i <= n; i++) cin >> p[i], f[i][i] = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
a[calc(i, j)][calc(i, j)] = 1;
for (int x = 1; x <= n; x++)
for (int y = 1; y <= n; y++)
if (x != y && f[x][i] && f[y][j]) {
double p1 = (x == i) ? p[x] : (1 - p[x]) / s[x];
double p2 = (y == j) ? p[y] : (1 - p[y]) / s[y];
a[calc(i, j)][calc(x, y)] -= p1 * p2;
}
}
gauss(n * n);
for (int i = 1; i <= n; i++)
cout << fixed << setprecision(6) << a[calc(i, i)][n * n + 1] << ' ';
return 0;
}