论文上的题目。。
《浅析竞赛中一类数学期望问题的解决方法》
这里是按照论文上的做法做的。。。。用一个path数组,path[i][j]代表通往j的最短路上与i相邻的编号最小的结点,这里先对每一个点进行一次bfs,求出如果以这个点作为终点所有点的与它们相邻结点的编号最小的结点,bfs是从终点出发,所以是后一个结点记录前一个结点,最后从起点向终点记忆化搜索就行
/*************************************************************************
> File Name: bzoj1415.cpp
> Author: tjw
> Mail:
> Created Time: 2014年10月14日 星期二 15时26分12秒
************************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#define ll long long
#define ls k<<1
#define rs k<<1|1
using namespace std;
const int MAXN=1010;
const int MAXE=1010;
struct EDGE
{
int v,next;
}edge[MAXE<<1];
int head[MAXN],size;
int degree[MAXN];
int path[MAXN][MAXN];
int dist[MAXN];
double dp[MAXN][MAXN];
void init()
{
memset(head,-1,sizeof(head));
memset(path,-1,sizeof(path));
memset(degree,0,sizeof(degree));
size=0;
}
void add_edge(int u,int v)
{
edge[size].v=v;
edge[size].next=head[u];
head[u]=size++;
}
void bfs(int x)
{
memset(dist,-1,sizeof(dist));
queue<int> q;
q.push(x);
dist[x]=0;
path[x][x]=x;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(dist[v]==-1)
{
dist[v]=dist[u]+1;
path[v][x]=u; //因为bfs是从终点出发,所以是后一个点存前一个
q.push(v);
}
else if(dist[v]==dist[u]+1&&u<path[v][x])
path[v][x]=u;
}
}
}
double dfs(int i,int j)
{
if(dp[i][j]!=-1)
return dp[i][j];
dp[i][j]=0;
int x=path[path[i][j]][j];
dp[i][j]+=dfs(x,j)+1;
if(x!=j)
{
for(int p=head[j];p!=-1;p=edge[p].next)
{
int v=edge[p].v;
dp[i][j]+=dfs(x,v)+1;
}
dp[i][j]/=degree[j]+1;
}
return dp[i][j];
}
int main()
{
int n,m,i;
while(scanf("%d%d",&n,&m)==2)
{
int s,t;
init();
scanf("%d%d",&s,&t);
int u,v;
while(m--)
{
scanf("%d%d",&u,&v);
degree[u]++;
degree[v]++;
add_edge(u,v);
add_edge(v,u);
}
for(i=1;i<=n;i++)
bfs(i);
for(i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
dp[i][j]=-1;
dp[i][i]=0;
}
printf("%.3f\n",dfs(s,t));
}
return 0;
}