一开始两个人分别站在 s s 和 t t ,一个人在每个点有 p p 的概率不动,或者等概率地随机走到一个相邻的点
求两个人在每个点相遇的概率
感觉是 [HNOI2013] [ H N O I 2013 ] 游走的加强版来着
设
di d i 表示点 i i 的点度, pi p i 表示在 i i 点不动的概率
ai,j a i , j 表示第一个人在 i i 点,第二个人在 j j 点的状态编号
f[i] f [ i ] 达到表示 i i 状态的期望步数, f[as,t]=1 f [ a s , t ] = 1
我们枚举一个点 x x 表示上一步第一个所在的位置, y y 表示第二个人的
当然 x≠y x ≠ y ,因为相等就已经停下了,不会对其他状态产生贡献了
可以很容易想到有 4 4 种转移
同样这个转移是存在环的,所以需要高斯消元,列式方法和上一题一样(同样的套路)
初值 G[as,t][n2+1]=1 G [ a s , t ] [ n 2 + 1 ] = 1 (因为 f[as,t]=1+∑… f [ a s , t ] = 1 + ∑ … )
#include
#define fp(i,a,b) for(register int i=a,I=b+1;i
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=405;
const double eps=1e-10;
typedef int arr[N];
typedef double d;
int n,m,s,t,Cnt;arr dg,a[N],mp[N];d p[N],ans[N],G[N][N];
inline int cmp(const d&x){return fabs(x)0:(x<0?-1:1);}
inline void Gauss(int n){
int mx;d t;
fp(i,1,n){mx=i;
fp(j,i,n)if(cmp(G[mx][i]-G[j][i]))mx=i;
if(mx^i)fp(j,i,n+1)swap(a[i][j],a[mx][j]);
fp(j,i+1,n)if(cmp(G[j][i])){
t=G[j][i]/G[i][i];
fp(k,i,n+1)G[j][k]-=t*G[i][k];
}
}
fd(i,n,1){
fp(j,i+1,n)G[i][n+1]-=ans[j]*G[i][j];
ans[i]=G[i][n+1]/G[i][i];
}
}
int main(){
#ifndef ONLINE_JUDGE
file("s");
#endif
scanf("%d%d%d%d",&n,&m,&s,&t);
while(m--){
int u,v;scanf("%d%d",&u,&v);
mp[u][v]=mp[v][u]=1;++dg[u],++dg[v];
}
fp(i,1,n)scanf("%lf",p+i),mp[i][i]=1;
fp(i,1,n)fp(j,1,n)a[i][j]=++Cnt;
G[a[s][t]][Cnt+1]=1;
fp(i,1,n)fp(j,1,n){
int pos=a[i][j];G[pos][pos]=1;
fp(x,1,n)if(mp[i][x])fp(y,1,n)if(mp[j][y]&&x^y){
d p1,p2;
if(i==x)p1=p[i];else p1=(1.0-p[x])/dg[x];
if(j==y)p2=p[j];else p2=(1.0-p[y])/dg[y];
G[pos][a[x][y]]+=-p1*p2;
}
}
Gauss(Cnt);
fp(i,1,n)printf("%.6lf ",ans[a[i][i]]);
return 0;
}