Problem
Solution
这题一看就联想起了HNOI游走那道题,仔细一看发现不对
发现这题的转移是有终点的,所以可以用Dp,加上题目是一张图,推荐用记忆化搜索
显然想到
表示当聪聪在点
可可在点
时聪聪抓可可步数的期望,先预处理聪聪在
可可在
时聪聪的选择路径
方程:
边界情况是 ,如果 两步之内可达
Code
#include<cctype>
#include<cstdio>
using namespace std;
#define rg register
template <typename _Tp> inline _Tp read(_Tp&x){
rg char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
const int N=1050;
struct Edge{int v,nxt;}a[N<<1];
int head[N],deg[N],dis[N][N],to[N][N],q[N],he,ta;
double f[N][N];
int n,m,_;
inline void add(int u,int v){a[++_].v=v,a[_].nxt=head[u],head[u]=_,++deg[u];}
double dfs(int x,int y){
if(f[x][y]!=-1.0)return f[x][y];
if(x==y)return f[x][y]=0;
if(to[x][y]==y)return f[x][y]=1;
if(to[to[x][y]][y]==y)return f[x][y]=1;
f[x][y]=0.0;
f[x][y]+=dfs(to[to[x][y]][y],y);
for(int i=head[y];i;i=a[i].nxt)
f[x][y]+=dfs(to[to[x][y]][y],a[i].v);
f[x][y]=f[x][y]/(double)(deg[y]+1)+1;
return f[x][y];
}
int main(){
int sa,sb;
read(n),read(m);
read(sa),read(sb);
for(rg int i=0,x,y;i<m;++i)read(x),read(y),add(x,y),add(y,x);
for(rg int i=1;i<=n;++i)
for(rg int j=1;j<=n;++j)f[i][j]=-1.0,to[i][j]=dis[i][j]=-1;
for(rg int s=1;s<=n;++s){
q[he=ta=1]=s;dis[s][s]=0;
while(he<=ta){
int x=q[he++];
for(int i=head[x];i;i=a[i].nxt)
if(-1==dis[s][a[i].v])
dis[s][a[i].v]=dis[s][x]+1,q[++ta]=a[i].v;
}
}
for(rg int x=1;x<=n;++x)
for(rg int t=1;t<=n;++t)if(x!=t&&dis[x][t]!=-1)
for(rg int i=head[x];i;i=a[i].nxt)
if(dis[x][t]==dis[a[i].v][t]+1&&(a[i].v<to[x][t]||to[x][t]==-1))
to[x][t]=a[i].v;
printf("%.3lf\n",dfs(sa,sb));
return 0;
}