bzoj1415: [Noi2005]聪聪和可可
spfa+dp。
首先用一个类似spfa的过程求出a[s][t],聪聪在s,可可在t时,聪聪第一步怎么走。
然后dp求出f[s][t],表示聪聪在s,可可在t的期望步数。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 1000 + 10; const int maxm = 2000 + 10; int g[maxn],v[maxm],next[maxm],eid; int n,m,s,t,u; int q[maxm*10],l,r; int deg[maxn],dist[maxn],a[maxn][maxn]; double f[maxn][maxn]; bool inque[maxn]; void addedge(int a,int b) { v[eid]=b; next[eid]=g[a]; g[a]=eid++; v[eid]=a; next[eid]=g[b]; g[b]=eid++; deg[a]++; deg[b]++; } void spfa(int s) { memset(dist,0x3f,sizeof(dist)); l=r=0; dist[s]=0; a[s][s]=s; for(int i=g[s];~i;i=next[i]) { dist[v[i]]=1; a[s][v[i]]=v[i]; inque[q[r++]=v[i]]=1; } while(l<r) { inque[u=q[l++]]=0; for(int i=g[u];~i;i=next[i]) if(dist[v[i]]>dist[u]+1) { dist[v[i]]=dist[u]+1; a[s][v[i]]=a[s][u]; if(!inque[v[i]]) inque[q[r++]=v[i]]=1; } else if(dist[v[i]]==dist[u]+1 && a[s][u]<a[s][v[i]] ) { a[s][v[i]]=a[s][u]; if(!inque[v[i]]) inque[q[r++]=v[i]]=1; } } //for(int i=1;i<=n;i++) printf("a[%d][%d]=%d\n",s,i,a[s][i]); } double dp(int s,int t) { if(f[s][t]>=0) return f[s][t]; int p=a[a[s][t]][t]; double sum=0; if(p==t) return f[s][t]=1; for(int i=g[t];~i;i=next[i]) sum+=dp(p,v[i]); sum+=dp(p,t); return f[s][t]=sum/(deg[t]+1)+1; } int main() { memset(g,-1,sizeof(g)); scanf("%d%d%d%d",&n,&m,&s,&t); for(int i=1,a,b;i<=m;i++) { scanf("%d%d",&a,&b); addedge(a,b); } for(int i=1;i<=n;i++) spfa(i); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) f[i][j]=-1; f[i][i]=0; } printf("%.3lf\n",dp(s,t)); return 0; }