BZOJ3270 博物馆(高斯消元+概率期望)
将两个人各自所在点视为状态,新建一个图。到达某个终点的概率等于其期望次数。那么高斯消元即可。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 410 int n,m,s,t,d[21][21],degree[21]; double a[N][N],p[21]; int trans(int x,int y){return (x-1)*n+y;} void gauss() { for (int i=1;i<n*n;i++) { int mx=i; for (int j=i+1;j<=n*n;j++) if (fabs(a[j][i])>fabs(a[mx][i])) mx=j; if (mx!=i) swap(a[i],a[mx]); for (int j=i+1;j<=n*n;j++) { double t=a[j][i]/a[i][i]; for (int k=i;k<=n*n+1;k++) a[j][k]-=t*a[i][k]; } } } int main() { #ifndef ONLINE_JUDGE freopen("bzoj3270.in","r",stdin); freopen("bzoj3270.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(),s=read(),t=read(); for (int i=1;i<=m;i++) { int x=read(),y=read(); degree[x]++,degree[y]++; d[x][y]=d[y][x]=1; } for (int i=1;i<=n;i++) d[i][i]=1; for (int i=1;i<=n;i++) cin>>p[i]; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) for (int x=1;x<=n;x++) for (int y=1;y<=n;y++) if (x!=y&&d[x][i]&&d[y][j]) { if (x==i) a[trans(i,j)][trans(x,y)]=p[x]; else if (d[x][i]) a[trans(i,j)][trans(x,y)]=(1-p[x])/degree[x]; if (y==j) a[trans(i,j)][trans(x,y)]*=p[y]; else if (d[y][j]) a[trans(i,j)][trans(x,y)]*=(1-p[y])/degree[y]; } for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[trans(i,j)][trans(i,j)]--; a[trans(s,t)][n*n+1]=-1; gauss(); for (int i=n*n;i>=1;i--) { a[i][n*n+1]/=a[i][i]; for (int j=i-1;j;j--) a[j][n*n+1]-=a[i][n*n+1]*a[j][i]; } for (int i=1;i<=n;i++) printf("%.6lf ",a[trans(i,i)][n*n+1]); return 0; }