Description
题解
既然是平均情况,显然就是求数学期望。我们会发现,每一个时刻猫鼠之间的最短路径一定是减小了,所以不会出现转圈的情况,所以可以用记忆化搜索,用
f[x][y]
表示猫在节点x,鼠在节点y,猫鼠相遇的期望值。题目中最终要的就是要知道猫的下一步会走到哪里,可以枚举每个点,然后BFS刷最短路,最后枚举一下,
O(N2)
的复杂度就可以构造出来。所以转移方程:
f[x][y]=1+∑DP(nxt,son[j])degree[y]+1
其中nxt表示猫下一步走到的节点。显然,如果x=y,
f[x][y]
=0,如果猫走的时候已经抓到了老鼠,那么
f[x][y]=1
;
给出代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1006
using namespace std;
int n,e,p1,p2,tot,lnk[maxn],son[maxn*2],nxt[maxn*2],ent[maxn],dis[maxn],que[maxn],
p[maxn][maxn];
bool vis[maxn];
double INF,f[maxn][maxn];
int _read(){
char ch=getchar();int sum=0;
while(!(ch>='0'&&ch<='9'))ch=getchar();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=getchar();
return sum;
}
void add(int x,int y){
nxt[++tot]=lnk[x];son[tot]=y;lnk[x]=tot;ent[x]++;
}
void bfs(int x){
memset(vis,1,sizeof(vis));
int hed=0,tal=1;que[1]=x;vis[x]=0;dis[x]=0;
while(hed!=tal){
for(int j=lnk[que[++hed]];j;j=nxt[j]) if(vis[son[j]]){
que[++tal]=son[j];
vis[son[j]]=0;
dis[son[j]]=dis[que[hed]]+1;
}
}
}
double DP(int x,int y){
if(x==y){return f[x][y]=0;}
if(f[x][y]!=INF)return f[x][y];
if(p[x][y]==y)return f[x][y]=1;
if(p[p[x][y]][y]==y)return f[x][y]=1;
f[x][y]=1;
f[x][y]+=DP(p[p[x][y]][y],y)/(ent[y]+1);
for(int j=lnk[y];j;j=nxt[j])if(son[j]!=x)
if(p[x][son[j]]!=son[j]) f[x][y]+=DP(p[p[x][y]][y],son[j])/(ent[y]+1);
return f[x][y];
}
int main(){
freopen("forest.in","r",stdin);
freopen("forest.out","w",stdout);
n=_read();e=_read();p1=_read();p2=_read();
for(int i=1,x,y;i<=e;i++)x=_read(),y=_read(),add(x,y),add(y,x);
memset(p,63,sizeof(p));memset(f,127,sizeof(f));INF=f[0][0];
for(int i=1;i<=n;i++){
bfs(i);
for(int j=1;j<=n;j++)
for(int k=lnk[j];k;k=nxt[k]) if((dis[son[k]]+1==dis[j])&&(son[k]<p[j][i]))p[j][i]=son[k];
}
printf("%.3lf",DP(p1,p2));
return 0;
}