【NOI2005】bzoj1415 聪聪和可可

来源:互联网 发布:dota2网络延迟 编辑:程序博客网 时间:2024/05/21 08:44

Description Input 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数。
第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号。
接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路。
所有的路都是无向的,即:如果能从A走到B,就可以从B走到A。
输入保证任何两个景点之间不会有多于一条路直接相连,且聪聪和可可之间必有路直接或间接的相连。 Output
输出1个实数,四舍五入保留三位小数,表示平均多少个时间单位后聪聪会把可可吃掉。

dp[i][j]表示猫在点i,老鼠在点j,猫吃掉老鼠的期望步数。猫走的下一步可以预处理出来,因此只需要枚举老鼠下一步走到哪里。因为猫走两步,老鼠走一步,二者的距离一定是越来越近的,也就是dp转移是一个拓扑图。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int oo=0x3f3f3f3f;int fir[1010],ne[2010],to[2010],f[1010][1010],que[2010],from[2010],dis[2010],n,m;double dp[1010][1010];void add(int num,int u,int v){    ne[num]=fir[u];    fir[u]=num;    to[num]=v;}double dfs(int u,int v){    if (dp[u][v]>=0) return dp[u][v];    if (u==v) return dp[u][v]=0;    if (f[u][v]==v||f[f[u][v]][v]==v) return dp[u][v]=1;    int x=f[f[u][v]][v],cnt=1;    for (int i=fir[v];i;i=ne[i]) cnt++;    dp[u][v]=1+dfs(x,v)/cnt;    for (int i=fir[v];i;i=ne[i]) dp[u][v]+=dfs(x,to[i])/cnt;    return dp[u][v];}int main(){    int hd,tl,u,v,s,t;    scanf("%d%d%d%d",&n,&m,&s,&t);    for (int i=1;i<=m;i++)    {        scanf("%d%d",&u,&v);        add(i<<1,u,v);        add(i<<1|1,v,u);    }    for (int i=1;i<=n;i++)    {        for (int j=1;j<=n;j++) dis[j]=oo;        dis[i]=0;        hd=1,tl=0;        for (int j=fir[i];j;j=ne[j])        {            dis[v=to[j]]=1;            que[++tl]=v;            from[v]=v;        }        while (hd<=tl)        {            u=que[hd++];            f[i][u]=from[u];            for (int j=fir[u];j;j=ne[j])                if (dis[u]+1<dis[v=to[j]]||(dis[u]+1==dis[v]&&from[u]<from[v]))                {                    if (dis[v]==oo) que[++tl]=v;                    dis[v]=dis[u]+1;                    from[v]=from[u];                }        }    }    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)            dp[i][j]=-1;    printf("%.3f\n",dfs(s,t));}
0 0
原创粉丝点击