[bzoj1415] 聪聪和可可
对于任意一对位置x,y我们可以找到聪聪的行走方案。(这个可以BFS跑)
然后我们用f[x,y]表示聪聪在x,可可在y抓住的期望时间,于是转移方程是:
if(x==y)f[x][y]=0, if(x走两步能到y)f[x][y]=1, else f[x][y]=(sigma(f[x_nxtpos][y_nxtpos])+1)/(d[y]+1);
记忆化搜索转移。
- 代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+2,M=2e3+2;
const int INF=0x3f3f3f3f;
int d[N],n,m,C,T;
int hed[N],nxt[M],to[M],cnt;
inline void adde(int u,int v){
cnt++;to[cnt]=v,nxt[cnt]=hed[u];hed[u]=cnt;
}
queue<int>q;
int going[N][N];
bool vis[N];
int dis[N];
inline void bfs(int s){
memset(vis,0,sizeof(vis));
dis[s]=0;
for(int i=1;i<=n;i++)dis[i]=INF;
vis[s]=true;
for(int i=hed[s];i;i=nxt[i]){
int v=to[i];
going[s][v]=v;vis[v]=true,dis[v]=1;
q.push(v);
}
vis[s]=true;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=hed[u];i;i=nxt[i]){
int v=to[i];
if(dis[v]>=dis[u]+1)
if(!vis[v]){
dis[v]=dis[u]+1;
going[s][v]=going[s][u];
vis[v]=true;
q.push(v);
}
else going[s][v]=min(going[s][u],going[s][v]);
}
}
}
double f[N][N];
double DP(int x,int y){
int arv=going[going[x][y]][y];
if(f[x][y]>0)return f[x][y];
if(x==y)return 0;
if(going[x][y]==y||arv==y)return f[x][y]=1;
double sum=DP(arv,y);
for(int i=hed[y];i;i=nxt[i])sum+=DP(arv,to[i]);
return f[x][y]=sum/(d[y]+1)+1;
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%d%d",&C,&T);
for(int i=1;i<=m;i++){
int u,v;scanf("%d%d",&u,&v);
adde(u,v);adde(v,u);
d[u]++,d[v]++;
}
for(int i=1;i<=n;i++)
bfs(i);
double ans=DP(C,T);
printf("%.3lf\n",ans);
}