Description
A:“大图书馆是一张n点m边的无向图,Marisa和Patchouli初始分别位于点X和点Y。每分钟,两人都有一次行动机会:当某人位于点i时,有pi的概率停留在点i,有1-pi的概率等概率随机选择点i的相邻节点之一并前往。若两人在某个点相遇,则行动停止。值得注意的是,两人在边上是不会相遇的,所以两人在某条边上迎面经过,只会错过而不会相遇。两人同时行动,求两人在每个点相遇的概率。”
B:“这不是CodeForces 113 D吗,还原度真高啊喂。”
A:“那改一改……不求在每个点相遇的概率,改成求两人在相遇前走过的路径长度期望和。”
B:“大同小异。”
A:“大图书馆的m条边的长度是可以修改的,两人的初始位置也是。”
B:“你不要让Patchouli太累了……”
Input
第一行三个正整数n、m、t,表示点数、边数和数据组数
以下m行,每行2个整数a,b,表示点a和点b之间有一条无向边
接下来一行n个实数表示pi,保证0.01<=pi<=0.99
以下t行,每行前m个整数表示每条边的长度,最后2个整数表示初始位置点X和点Y
Output
共t行,每行一个实数表示两人在相遇前走过的路径长度期望和(保留2位小数)
对每个(a,b),将两人起点分别在(a,b)时的答案设为变量,边长看做常量,高斯消元可以把每个变量用常量的线性组合表示出来,于是可以O(m)回答一个询问。
#include<bits/stdc++.h> int _(){ int x=0,c=getchar(); while(c<48)c=getchar(); while(c>47)x=x*10+c-48,c=getchar(); return x; } int n,m,t,ev[555],id[25][25],idp=0; double p[25],A[333][633]; struct edge{ int to,id; }; std::vector<edge>es[25]; int main(){ n=_();m=_();t=_(); for(int i=1;i<=n;++i)for(int j=1;j<i;++j)id[i][j]=id[j][i]=++idp; for(int i=1;i<=m;++i){ int a=_(),b=_(); es[a].push_back((edge){b,idp+i}); es[b].push_back((edge){a,idp+i}); } for(int i=1;i<=n;++i)scanf("%lf",p+i); for(int w=1;w<=n;++w)for(int u=1;u<w;++u){ double*f=A[id[w][u]],p1,p2; for(int i=0;i<es[w].size();++i){ p1=(1-p[w])*p[u]/es[w].size(); p2=(1-p[w])*(1-p[u])/(es[w].size()*es[u].size()); edge e1=es[w][i]; f[id[e1.to][u]]+=p1; f[e1.id]+=p1; for(int j=0;j<es[u].size();++j){ edge e2=es[u][j]; f[id[e1.to][e2.to]]+=p2; f[e1.id]+=p2; f[e2.id]+=p2; } } for(int j=0;j<es[u].size();++j){ double p1=(1-p[u])*p[w]/es[u].size(); edge e2=es[u][j]; f[id[w][e2.to]]+=p1; f[e2.id]+=p1; } f[id[w][u]]+=p[w]*p[u]-1; } for(int i=1;i<=idp;++i){ int w=i; for(int j=i+1;j<=idp;++j)if(fabs(A[j][i])>fabs(A[w][i]))w=j; if(w!=i)for(int k=1;k<=idp+m;++k)std::swap(A[i][k],A[w][k]); double v=A[i][i]; for(int k=i;k<=idp+m;++k)A[i][k]/=v; for(int j=1;j<=idp;++j)if(j!=i&&fabs(v=A[j][i])>1e-11) for(int k=i;k<=idp+m;++k)A[j][k]-=A[i][k]*v; } for(;t;--t){ for(int i=1;i<=m;++i)ev[i]=_(); int x=_(),y=_(); if(x==y)puts("0.00"); else{ double*f=A[id[x][y]]+idp,s=0; for(int i=1;i<=m;++i)s+=f[i]*ev[i]; printf("%.2f\n",fabs(s)); } } return 0; }