Time Limit: 10 Sec Memory Limit: 162 MB
Description
Input
数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数。 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号。 接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路。 所有的路都是无向的,即:如果能从A走到B,就可以从B走到A。 输入保证任何两个景点之间不会有多于一条路直接相连,且聪聪和可可之间必有路直接或间接的相连。
Output
输出1个实数,四舍五入保留三位小数,表示平均多少个时间单位后聪聪会把可可吃掉。
题目分析
先预处理
r
e
m
[
u
]
[
v
]
rem[u][v]
rem[u][v]表示当前聪聪在
u
u
u,可可在
v
v
v时,聪聪下一个会到达的点
可以直接以每个点
v
v
v为起点跑最短路,并记录令
d
i
s
[
u
]
dis[u]
dis[u]最小的上一个结点
p
r
e
[
u
]
pre[u]
pre[u]
那么有
r
e
m
[
u
]
[
v
]
=
p
r
e
[
u
]
rem[u][v]=pre[u]
rem[u][v]=pre[u]
预处理完后的DP就比较好想了
d
p
[
u
]
[
v
]
dp[u][v]
dp[u][v]表示当前聪聪在
u
u
u,可可在
v
v
v时,聪聪与可可相遇的期望步数
特别注意题目中 聪聪在一个时间段能走两步!
于是边界条件
u
=
=
v
u==v
u==v时
d
p
[
u
]
[
v
]
=
0
dp[u][v]=0
dp[u][v]=0
r
e
m
[
u
]
[
v
]
=
=
v
∣
∣
r
e
m
[
r
e
m
[
u
]
[
v
]
]
[
v
]
=
=
v
rem[u][v]==v\ ||\ rem[\ rem[u][v]\ ][v]==v
rem[u][v]==v ∣∣ rem[ rem[u][v] ][v]==v时
d
p
[
u
]
[
v
]
=
1
dp[u][v]=1
dp[u][v]=1
其余情况下有(记
t
=
r
e
m
[
r
e
m
[
u
]
[
v
]
]
[
v
]
t=rem[\ rem[u][v]\ ][v]
t=rem[ rem[u][v] ][v])
d
p
[
u
]
[
v
]
=
D
P
(
t
,
v
)
+
∑
D
P
(
t
,
j
)
d
e
g
[
v
]
+
1
+
1
dp[u][v]=\frac{DP(t,v)+\sum DP(t,j)}{deg[v]+1}+1
dp[u][v]=deg[v]+1DP(t,v)+∑DP(t,j)+1
套上记搜即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
typedef double dd;
int read()
{
int x=0,f=1;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return x*f;
}
const int maxn=1010;
int n,m,x,y;
struct node{int v,nxt;}E[maxn<<1];
int head[maxn],tot;
int d[maxn],vis[maxn],pre[maxn];
int rem[maxn][maxn],deg[maxn];
int judge[maxn][maxn];
dd dp[maxn][maxn];
void add(int u,int v)
{
E[++tot].nxt=head[u];
E[tot].v=v;
head[u]=tot;
}
void SPFA(int s)
{
memset(d,67,sizeof(d)); d[s]=0;
queue<int> q; q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop(); vis[u]=0;
for(int i=head[u];i;i=E[i].nxt)
{
int v=E[i].v;
if(d[v]>d[u]+1)
{
d[v]=d[u]+1; pre[v]=u;
if(!vis[v])q.push(v),vis[v]=1;
}
if(d[v]==d[u]+1)
pre[v]=u<pre[v]?u:pre[v];
}
}
for(int i=1;i<=n;++i) rem[i][s]=pre[i];
}
dd DP(int u,int v)
{
if(judge[u][v]) return dp[u][v];
judge[u][v]=1;
if(u==v) return dp[u][v]=0;
if(rem[u][v]==v||rem[rem[u][v]][v]==v) return dp[u][v]=1;//cout<<"hh"<<endl;
int t=rem[rem[u][v]][v];
dd res=DP(t,v),cnt=0;
for(int i=head[v];i;i=E[i].nxt)
res+=DP(t,E[i].v);
return dp[u][v]=res/(deg[v]+1)+1;
}
int main()
{
n=read();m=read(); x=read();y=read();
for(int i=1;i<=m;++i)
{
int u=read(),v=read();
deg[u]++; deg[v]++;
add(u,v); add(v,u);
}
for(int i=1;i<=n;++i) SPFA(i);
printf("%.3lf",DP(x,y));
return 0;
}