记录编号 |
359798 |
评测结果 |
AAAAAAAAAA |
题目名称 |
[NOI 2005]聪聪与可可 |
最终得分 |
100 |
用户昵称 |
FoolMike |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
0.121 s |
提交时间 |
2016-12-24 21:46:16 |
内存使用 |
30.62 MiB |
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
typedef double db;
const int N=1010,M=10010;
int n,m,x,y,du[N],w[M],head[M],next[M],tail[M],cnt;
void add(int f,int t){
w[++cnt]=t;du[f]++;
if (!head[f]) head[f]=tail[f]=cnt;
else tail[f]=next[tail[f]]=cnt;
}
db ans;
int f[N][N];
//dp[i][j][k]表示聪聪和可可分别在i,j位置
//k=0表示该可可走,k>0表示该聪聪走k步
void spfa(int s){
int *dis=f[s];
for (int i=1;i<=n;i++) dis[i]=1e9;
dis[s]=0;
queue<int> Q;
Q.push(s);
while (!Q.empty()){
int v=Q.front();Q.pop();
for (int i=head[v];i;i=next[i])
if (dis[w[i]]>dis[v]+1)
dis[w[i]]=dis[v]+1,Q.push(w[i]);
}
}
bool vis[N][N][3];db dp[N][N][3];
db p(int x,int y,int k){//返回dp[x][y][k]的值
if (x==y) return 0;
if (vis[x][y][k]) return dp[x][y][k];
vis[x][y][k]=1;
db ans=0;
if (!k){
db P=1.0/(du[y]+1);
ans+=(1+p(x,y,2))*P;
for (int i=head[y];i;i=next[i])
if (x!=w[i]) ans+=(1+p(x,w[i],2))*P;
}else
if (k==1){
int d=f[x][y]-1,pos=n;
for (int i=head[x];i;i=next[i]){
int v=w[i];
if (f[v][y]==d) pos=min(v,pos);
}
ans+=p(pos,y,0);
}else
if (k==2){
int d=f[x][y]-1,pos=n;
for (int i=head[x];i;i=next[i]){
int v=w[i];
if (f[v][y]==d) pos=min(v,pos);
}
ans+=p(pos,y,1);
}
return dp[x][y][k]=ans;
}
int main()
{
freopen("cchkk.in","r",stdin);
freopen("cchkk.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&x,&y);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (i!=j) f[i][j]=1e9;
for (int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
for (int i=1;i<=n;i++) spfa(i);
printf("%.3lf\n",x!=y?1+p(x,y,2):0);
return 0;
}