题目链接:聪聪和可可
一道水题……开始还看错题了,以为边带权……强行(O(n^3))预处理……
首先,我们显然可以预处理出一个数组(p[u][v])表示可可在点(u),聪聪在点(v)的时候聪聪下一步会往哪里走。然后……一个记忆化搜索就轻易地解决掉了……
至于转移方程吗,我觉得也没有必要写了……你要是实在不知道就看一看代码吧……
下面贴代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) #define N 1010 using namespace std; typedef double llg; int n,E,C,M,dis[N],p[N][N],fr[N],d[N],ld; int head[N],next[N<<1],to[N<<1],tt,du[N]; llg f[N][N]; bool vis[N],w[N][N]; void solve(int S){ for(int i=1;i<=n;i++) dis[i]=vis[i]=0; vis[S]=1; d[ld=1]=S; du[S]++; for(int l=1,u;u=d[l],l<=ld;l++) for(int i=head[u],v;v=to[i],i;i=next[i]) if(!vis[v]) dis[v]=dis[u]+1,vis[v]=1,d[++ld]=v,fr[v]=u; else if(dis[v]==dis[u]+1) fr[v]=min(fr[v],u); for(int i=1;i<=n;i++) p[S][i]=fr[i]; } llg search(int u,int v){ if(w[u][v]) return f[u][v]; if(p[u][v]==u || p[u][p[u][v]]==u) return 1; w[u][v]=1; for(int i=head[u];i;i=next[i]) f[u][v]+=search(to[i],p[u][p[u][v]])+1; f[u][v]+=search(u,p[u][p[u][v]])+1; return f[u][v]/=(llg)du[u]; } int main(){ File("a"); scanf("%d %d %d %d",&n,&E,&C,&M); for(int i=1,x,y;i<=E;i++){ scanf("%d %d",&x,&y); du[x]++; du[y]++; to[++tt]=y;next[tt]=head[x];head[x]=tt; to[++tt]=x;next[tt]=head[y];head[y]=tt; } for(int i=1;i<=n;i++) solve(i),w[i][i]=1; printf("%.3lf",search(M,C)); return 0; }