[BZOJ 3270] 博物馆
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=3270
[算法]
记fi,j表示第一个人在i , 第二个人在j的概率
高斯消元即可
时间复杂度 : O(N ^ 6)
[代码]
#include<bits/stdc++.h> using namespace std; const int N = 30; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const double eps = 1e-9; struct edge { int to , nxt; } e[N * N * 2]; int n , m , A , B , tot; int head[N * N]; double deg[N * N] , a[N * N][N * N] , b[N * N] , p[N * N] , ans[N * N]; template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); } template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline int id(int x , int y) { return (x - 1) * n + y; } inline void addedge(int u , int v) { ++tot; e[tot] = (edge){v , head[u]}; head[u] = tot; } int dcmp(double x) { if (x<=eps&&x>=-eps) return 0; return (x>0)?1:-1; } int main() { scanf("%d%d%d%d" , &n , &m , &A , &B); for (int i = 1; i <= m; i++) { int u , v; scanf("%d%d" , &u , &v); addedge(u , v); addedge(v , u); deg[u] += 1.0; deg[v] += 1.0; } for (int i = 1; i <= n; i++) scanf("%lf" , &p[i]); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { a[id(i , j)][id(i , j)] = 1; if (i != j) a[id(i , j)][id(i , j)] -= p[i] * p[j]; for (int k = head[i]; k; k = e[k].nxt) if (e[k].to != j && e[k].to != i) a[id(i , j)][id(e[k].to , j)] -= (1 - p[e[k].to]) / deg[e[k].to] * p[j]; for (int k = head[j]; k; k = e[k].nxt) if (i != e[k].to && j != e[k].to) a[id(i , j)][id(i , e[k].to)] -= (1 - p[e[k].to]) / deg[e[k].to] * p[i]; for (int k = head[i]; k; k = e[k].nxt) { for (int l = head[j]; l; l = e[l].nxt) { if (e[k].to != e[l].to) a[id(i , j)][id(e[k].to , e[l].to)] -= (1 - p[e[k].to]) / deg[e[k].to] * (1 - p[e[l].to]) / deg[e[l].to]; } } } } b[id(A , B)] = 1.0; for (int i=1;i<=n*n;++i) { int num=i; for (int j=i+1;j<=n*n;++j) if (dcmp(a[j][i]-a[num][i])>0) num=j; if (num!=i) { for (int j=1;j<=n*n;++j) swap(a[num][j],a[i][j]); swap(b[num],b[i]); } for (int j=i+1;j<=n*n;++j) if (dcmp(a[j][i])) { double t=a[j][i]/a[i][i]; for (int k=1;k<=n*n;++k) a[j][k]-=t*a[i][k]; b[j]-=b[i]*t; } } for (int i=n*n;i>=1;--i) { for (int j=i+1;j<=n*n;++j) b[i]-=a[i][j]*ans[j]; ans[i]=b[i]/a[i][i]; } for (int i = 1; i <= n; i++) printf("%.6lf " , ans[id(i , i)]); printf("\n"); return 0; }