bzoj1415: [Noi2005]聪聪和可可 记忆化搜索

来源:互联网 发布:linux如何查看文件大小 编辑:程序博客网 时间:2024/06/05 08:04

由于猫每次都走最短路,我们可以把老鼠所在每个点时猫会怎么走给处理出来。

若i==j 则f[i][j]=0

若p[i][j]==j||p[p[i][j]][j]==j则f[i][j]=1

否则令temp=p[p[i][j]][j],则有


其中degree[j]表示j的连边数量

#include <iostream>#include <cmath>#include <algorithm>#include <cstdio>#include <cstring>#include <vector>#include <queue>using namespace std;#define pb(a) push_back(a)#define maxn 1100double f[maxn][maxn];int pl[maxn][maxn];int n,m,st,ed,deg[maxn];vector<int>g[maxn];int dis[maxn],vis[maxn],from[maxn];void spfa(int s){    memset(dis,0x3f3f3f3f,sizeof(dis));    dis[s]=0;    queue<int>q;    q.push(s);    while(!q.empty())    {        int u=q.front();        q.pop();        vis[u]=0;        int len=g[u].size();        for(int i=0;i<len;i++)        {            int v=g[u][i];            if(dis[v]>dis[u]+1 || (dis[v]==dis[u]+1&&u<from[v]))            {                dis[v]=dis[u]+1;                from[v]=u;                if(!vis[v])                {                    vis[v]=1;                    q.push(v);                }            }        }    }    for(int i=1;i<=n;i++)    {        if(i==s) continue;        pl[i][s]=from[i];    }}double dfs(int x,int y){    if(x==y) return f[x][y]=0.0;    if(y==pl[x][y]) return f[x][y]=1.0;    if(y==pl[pl[x][y]][y]) return f[x][y]=1.0;    if(f[x][y]>=-1e-7) return f[x][y];    double re=0;    int v=pl[pl[x][y]][y];    int len=g[y].size();    for(int i=0;i<len;i++)    {        re+=dfs(v,g[y][i]);    }    re+=dfs(v,y);    re=re/double(deg[y]+1)+1;    return f[x][y]=re;}int main(){    scanf("%d%d",&n,&m);    scanf("%d%d",&st,&ed);    for(int i=1;i<=m;i++)    {        int a,b;        scanf("%d%d",&a,&b);        g[a].pb(b);        deg[a]++;        g[b].pb(a);        deg[b]++;    }    for(int i=1;i<=n;i++)        spfa(i);    memset(f,0xc2,sizeof f);    printf("%.3f",dfs(st,ed));    return 0;}


0 0
原创粉丝点击