期望DP + 记忆化搜索
感觉最难的地方是预处理,处理完后的转移方程很显然
设
p
[
i
,
j
]
p[i,j]
p[i,j] 表示聪聪在
i
i
i 点,可可在
j
j
j 点时,聪聪的下一步会走到哪里
用
n
n
n 遍 bfs 预处理即可
设
f
[
i
,
j
]
f[i,j]
f[i,j] 表示聪聪在
i
i
i 点,可可在
j
j
j 点时答案的期望值
设
d
i
d_i
di 表示点
i
i
i 的度数
设
e
[
i
,
j
]
e[i,j]
e[i,j] 表示第
j
j
j 个与
i
i
i 相邻的点
那么,转移方程显然是:
f
[
i
,
j
]
=
1
+
{
∑
k
=
1
d
j
f
[
p
[
p
[
i
,
j
]
,
j
]
,
e
[
j
,
k
]
]
}
+
f
[
p
[
p
[
i
,
j
]
,
j
]
,
j
]
d
j
+
1
f[i,j]=1+\frac{\{ \sum\limits_{k=1}^{d_j}f[p[p[i,j],j],e[j,k]]\}+f[p[p[i,j],j],j]}{d_j+1}
f[i,j]=1+dj+1{k=1∑djf[p[p[i,j],j],e[j,k]]}+f[p[p[i,j],j],j]
特别地:
- f [ i , i ] = 0 f[i,i]=0 f[i,i]=0
- 如果 p [ i , j ] = j p[i,j]=j p[i,j]=j 或 p [ p [ i , j ] , j ] = j p[p[i,j],j]=j p[p[i,j],j]=j,则 f [ i , j ] = 1 f[i,j]=1 f[i,j]=1
正确性显然
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
const int Maxn=1010;
const int inf=0x3f3f3f3f;
int p[Maxn][Maxn],d[Maxn];
int g[Maxn][Maxn],dis[Maxn];
double f[Maxn][Maxn];
bool vis[Maxn];
bool flag[Maxn][Maxn];
vector <int> e[Maxn];
int n,m,s,t;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return s*w;
}
inline void add(int x,int y)
{e[x].push_back(y);}
void bfs(int s)
{
queue <int> q;
fill(dis+1,dis+1+n,inf);
memset(vis,0,sizeof(vis));
dis[s]=0,vis[s]=1,q.push(s);
while(q.size())
{
int x=q.front();
q.pop();
for(int i=0;i<e[x].size();++i)
{
int y=e[x][i];
if(dis[y]>dis[x]+1)
{
dis[y]=dis[x]+1;
if(!vis[y])vis[y]=1,q.push(y);
}
}
}
for(int i=1;i<=n;++i)
g[s][i]=dis[i];
}
double dfs(int i,int j)
{
if(flag[i][j])return f[i][j];
flag[i][j]=1.0;
if(i==j)return f[i][j]=0.0;
if(p[i][j]==j || p[p[i][j]][j]==j)
return f[i][j]=1.0;
for(int k=0;k<e[j].size();++k)
{
int x=e[j][k];
f[i][j]+=dfs(p[p[i][j]][j],x);
}
f[i][j]+=dfs(p[p[i][j]][j],j);
f[i][j]/=(1.0*(d[j]+1.0));
f[i][j]+=1.0;
return f[i][j];
}
int main()
{
n=read(),m=read(),s=read(),t=read();
for(int i=1;i<=m;++i)
{
int x=read(),y=read();
add(x,y),add(y,x);
}
for(int i=1;i<=n;++i)
sort(e[i].begin(),e[i].end());
for(int i=1;i<=n;++i)
bfs(i),d[i]=e[i].size();
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
{
int tmp=inf,pos;
for(int k=0;k<e[i].size();++k)
{
int x=e[i][k];
if(g[x][j]<tmp)
tmp=g[x][j],pos=x;
}
p[i][j]=pos;
}
printf("%.3lf\n",dfs(s,t));
return 0;
}