f[i][j]表示i点追j点的期望步数。。。
这题必须spfa不能bfs。
且复杂度不会炸(仅1000条边)
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> #define maxv 1050 #define maxe 2050 #define inf 1000000007 #define eps 1e-6 using namespace std; int n,m,b,t,x,y,g[maxv],nume=0; int d[maxv],p[maxv][maxv],dis[maxv]; double f[maxv][maxv]; bool vis[maxv]; queue <int> q; struct edge { int v,nxt; }e[maxe]; void addedge(int u,int v) { e[++nume].v=v; e[nume].nxt=g[u]; g[u]=nume; } void reset() { for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) p[i][j]=inf; } void pre_bfs(int x) { while (!q.empty()) q.pop(); for (int i=1;i<=n;i++) { vis[i]=false; dis[i]=inf; } dis[x]=0; for (int i=g[x];i;i=e[i].nxt) { int v=e[i].v; vis[v]=true;dis[v]=1;q.push(v); p[x][v]=v; } while (!q.empty()) { int head=q.front();q.pop(); for (int i=g[head];i;i=e[i].nxt) { int v=e[i].v; if ((dis[v]>dis[head]+1) || ((dis[v]==dis[head]+1) && (p[x][v]>p[x][head]))) { dis[v]=dis[head]+1; p[x][v]=p[x][head]; if (!vis[v]) q.push(v); } } vis[head]=false; } return; } double dp(int x,int y) { if (x==y) return 0; if (f[x][y]>eps) return f[x][y]; if ((p[x][y]==y) || (p[p[x][y]][y]==y)) return 1; double ret=0; for (int i=g[y];i;i=e[i].nxt) { int v=e[i].v; if (p[p[x][y]][y]==y) ret++; else if (p[x][y]==y) ret++; else ret+=dp(p[p[x][y]][y],v); } if (p[p[x][y]][y]==y) ret++; else if (p[x][y]==y) ret++; else ret+=dp(p[p[x][y]][y],y); ret/=(d[y]+1);ret=ret+1; f[x][y]=ret; return ret; } int main() { memset(d,0,sizeof(d)); scanf("%d%d",&n,&m);scanf("%d%d",&b,&t); for (int i=1;i<=m;i++) { scanf("%d%d",&x,&y); addedge(x,y);addedge(y,x); d[x]++;d[y]++; } reset(); for (int i=1;i<=n;i++) pre_bfs(i); for (int i=1;i<=n;i++) p[i][i]=inf; printf("%.3lf\n",dp(b,t)); return 0; }