• bzoj 1415 [Noi2005]聪聪和可可——其实无环的图上概率


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1415

    乍一看和“游走”一样。于是高斯消元。n^2状态,复杂度n^6……

    看看TJ,发现因为聪聪不是随便走的,所以聪聪一直逼近可可。故其实无环。可以记搜。

    (1A还是不错的)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=1005;
    int n,m,l0,l1,nxt[N][N],dfn[N],du[N];
    double dp[N][N];
    bool vis[N],vs[N][N];
    priority_queue<int,vector<int>,greater<int> >ed[N];
    void add(int x,int y)
    {
        ed[x].push(y);ed[y].push(x);
        du[x]++;du[y]++;
    }
    void bfs(int cr)
    {
        priority_queue<int,vector<int>,greater<int> >tp;
        memset(vis,0,sizeof vis);memset(dfn,0,sizeof dfn);
        queue<int> q;q.push(cr);vis[cr]=1;nxt[cr][cr]=cr;
        while(q.size())
        {
            int k=q.front();q.pop();
            tp=ed[k];
            while(tp.size())
            {
                int v=tp.top();tp.pop();
                if(vis[v])continue;
                dfn[v]=dfn[k]+1;vis[v]=1;q.push(v);
                if(dfn[v]>2)nxt[v][cr]=nxt[k][cr];
                else nxt[v][cr]=v;
            }
        }
    }
    double dfs(int x,int y)//coco->x ,cncn->y
    {
    //    printf("x=%d y=%d
    ",x,y);
        if(vs[x][y])return dp[x][y];vs[x][y]=1;
        if(nxt[x][y]==x){/*printf("rt x=%d y=%d
    ",x,y);*/return dp[x][y]=1;}
        double ret=(dfs(x,nxt[x][y])+(nxt[x][y]!=x))/(du[x]+1);
        priority_queue<int,vector<int>,greater<int> >tp=ed[x];//每层定义 
    //    printf("siz[%d]=%d
    ",x,tp.size());
        while(tp.size())
        {
            int v=tp.top();tp.pop();
    //        printf("v=%d nxt[%d][%d]=%d
    ",v,x,y,nxt[x][y]);
            ret+=(dfs(v,nxt[x][y])+(nxt[x][y]!=v))/(du[x]+1);
        }
    //    printf("ret=%.3lf
    ",ret);
        return dp[x][y]=ret;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&l0,&l1);int x,y;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);add(x,y);
        }
        for(int i=1;i<=n;i++)bfs(i);
        printf("%.3lf",dfs(l1,l0));
        return 0;
    }
    版本1

    看看TJ,发现判断得那么纠结是因为x==y时正常应返回0。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=1005;
    int n,m,l0,l1,nxt[N][N],dfn[N],du[N];
    double dp[N][N];
    bool vis[N],vs[N][N];
    priority_queue<int,vector<int>,greater<int> >ed[N];
    void add(int x,int y)
    {
        ed[x].push(y);ed[y].push(x);
        du[x]++;du[y]++;
    }
    void bfs(int cr)
    {
        priority_queue<int,vector<int>,greater<int> >tp;
        memset(vis,0,sizeof vis);memset(dfn,0,sizeof dfn);
        queue<int> q;q.push(cr);vis[cr]=1;nxt[cr][cr]=cr;
        while(q.size())
        {
            int k=q.front();q.pop();
            tp=ed[k];
            while(tp.size())
            {
                int v=tp.top();tp.pop();
                if(vis[v])continue;
                dfn[v]=dfn[k]+1;vis[v]=1;q.push(v);
                if(dfn[v]>2)nxt[v][cr]=nxt[k][cr];
                else nxt[v][cr]=v;
            }
        }
    }
    double dfs(int x,int y)//coco->x ,cncn->y
    {
        if(vs[x][y])return dp[x][y];vs[x][y]=1;
        if(x==y)return dp[x][y]=0;//
        if(nxt[x][y]==x)return dp[x][y]=1;
        double ret=dfs(x,nxt[x][y])/(du[x]+1)+1;
        priority_queue<int,vector<int>,greater<int> >tp=ed[x];//每层定义 
        while(tp.size())
        {
            int v=tp.top();tp.pop();
            ret+=dfs(v,nxt[x][y])/(du[x]+1);
        }
        return dp[x][y]=ret;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&l0,&l1);int x,y;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);add(x,y);
        }
        for(int i=1;i<=n;i++)bfs(i);
        printf("%.3lf",dfs(l1,l0));
        return 0;
    }
    版本2

    但是自己代码巨慢……想来是用了优先队列的缘故(为了标号字典序)。尝试改一改。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=1005;
    int n,m,l0,l1,nxt[N][N],dfn[N],du[N],head[N],xnt;
    double dp[N][N];
    bool vis[N],vs[N][N];
    priority_queue<int,vector<int>,greater<int> >ed[N];
    struct Edge{
        int next,to;
        Edge(int n=0,int t=0):next(n),to(t) {}
    }edge[N<<1];
    void add(int x,int y)
    {
        edge[++xnt]=Edge(head[x],y);head[x]=xnt;
        edge[++xnt]=Edge(head[y],x);head[y]=xnt;
        ed[x].push(y);ed[y].push(x);
        du[x]++;du[y]++;
    }
    void bfs(int cr)
    {
        priority_queue<int,vector<int>,greater<int> >tp;
        memset(vis,0,sizeof vis);memset(dfn,0,sizeof dfn);
        queue<int> q;q.push(cr);vis[cr]=1;nxt[cr][cr]=cr;
        while(q.size())
        {
            int k=q.front();q.pop();
            tp=ed[k];
            while(tp.size())
            {
                int v=tp.top();tp.pop();
                if(vis[v])continue;
                dfn[v]=dfn[k]+1;vis[v]=1;q.push(v);
                if(dfn[v]>2)nxt[v][cr]=nxt[k][cr];
                else nxt[v][cr]=v;
            }
        }
    }
    double dfs(int x,int y)//coco->x ,cncn->y
    {
        if(vs[x][y])return dp[x][y];vs[x][y]=1;
        if(x==y)return dp[x][y]=0;//
        if(nxt[x][y]==x)return dp[x][y]=1;
        double ret=dfs(x,nxt[x][y])/(du[x]+1)+1;
        for(int i=head[x];i;i=edge[i].next)
            ret+=dfs(edge[i].to,nxt[x][y])/(du[x]+1);
        return dp[x][y]=ret;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&l0,&l1);int x,y;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);add(x,y);
        }
        for(int i=1;i<=n;i++)bfs(i);
        printf("%.3lf",dfs(l1,l0));
        return 0;
    }

    结果只是快了28ms。

    别人用一些方法保证字典序。

    这个人bfs+两步保证dis最小的前提下调整标号至最小。https://blog.csdn.net/clove_unique/article/details/62237321

    这个人spfa的同时判断标号。(但只能记录一步的pre)https://blog.csdn.net/PoPoQQQ/article/details/40896403(bfs因为是bfs所以不能边求dis边调整标号)

    可是我都没记录dis。用的dfn。所以懒得改了……比较欣赏第一个人的写法。

  • 相关阅读:
    谈谈toLocaleString()
    如何理解NaN?
    Element--->>>最新骨架屏Skeleton使用
    自定义select组件
    微信小程序之配置业务域名踩过的坑
    Vue watch监听 date中的变量 与 数组或者对象的数据变化
    Vue + Element table的@select方法获取当table中的id值都相同时,获取他们索引
    Vue + Element table中的某行触发enter事件后,使该行disabled
    Vue + Element tree树形控件的懒加载使用
    Vue web使用LeapFTP 上传到服务器
  • 原文地址:https://www.cnblogs.com/Narh/p/9206642.html
Copyright © 2020-2023  润新知