Time:2016.08.24
Author:xiaoyimi
转载注明出处谢谢
传送门1
传送门2
思路:
f[x][y]表示猫走到x,老鼠走到y时猫抓到老鼠的步数期望
f[x][y]−>f[g[g[x][y]][y]][w[y]]
f[x][y]−>f[g[g[x][y]][y]][y]
g[x][y]表示x到y的最短路径上与x相邻的编号最小的点
w[y]表示y能到达的所有点
x=y时f[x][y]=0
g[x][y]=y或g[g[x][y]][y]=y时f[x][y]=1
记忆化搜索就可以了
g数组预处理可以用SPFA+乱搞
复杂度
O(n2)
代码:
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#define M 1001
using namespace std;
int tot,n,m,S,T;
int first[M],d[M],g[M][M],dis[M][M];
double f[M][M];
bool vis[M];
int in()
{
char ch=getchar();int t=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar();
return t;
}
struct edge{
int u,v,next;
}e[M<<1];
struct node{
int D,mi,id;
};
queue<int>q;
void add(int x,int y)
{
e[++tot]=(edge){x,y,first[x]};first[x]=tot;++d[x];
e[++tot]=(edge){y,x,first[y]};first[y]=tot;++d[y];
}
void spfa(int x)
{
memset(dis[x],63,sizeof(dis[x]));
q.push(x);
dis[x][x]=0;
for (;!q.empty();q.pop())
{
int now=q.front();
for (int i=first[now];i;i=e[i].next)
if (dis[x][e[i].v]>dis[x][now]+1)
{
dis[x][e[i].v]=dis[x][now]+1,
g[x][e[i].v]=(now==x?e[i].v:g[x][now]);
if (!vis[e[i].v]) vis[e[i].v]=1,q.push(e[i].v);
}
else if (dis[x][e[i].v]==dis[x][now]+1)
g[x][e[i].v]=min(g[x][e[i].v],g[x][now]);
vis[now]=0;
}
}
void dfs(int x,int y)
{
if (f[x][y]||x==y) return;
f[x][y]=1;
if (g[x][y]==y||g[g[x][y]][y]==y) return;
double sum=0;
int z=g[g[x][y]][y];
for (int i=first[y];i;i=e[i].next)
dfs(z,e[i].v),
sum+=f[z][e[i].v];
dfs(z,y);
f[x][y]+=(sum+f[z][y])/(d[y]+1);
}
main()
{
n=in();m=in();
S=in();T=in();
for (int i=1;i<=m;++i)
add(in(),in());
for (int i=1;i<=n;++i) spfa(i);
dfs(S,T);
printf("%.3lf\n",f[S][T]);
}