• POJ 2449 A*+SPFA


    A*算法求第k短路流程:

    1)计算h[],即当前点到t的估计值

      若为有向图,建立反向图求出h[]。若为无向图,可直接求解h[]。可通过SPFA求解。

    2)A*搜索

      每次找到新节点就直接加入队列,计算出估价函数f[]=g[]+h[],然后加入优先队列中。(此步不可优化,否则可能造成失解)

      常用STL priority_queue实现,要注意默认是大根堆,可重载<实现小根堆。

    3)若根入队k次,返回

    ADD:

    该题几个注意事项及优化:

      a)若起始点h值==INF,不搜。

      b)若一个点入队超过k次,不搜。

      c)邻接表代替邻接矩阵,防止重边。

      d)该题中若s==t,距离为0的路径不能计入。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    #include <utility>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)>(y)?(y):(x))
    #define INF 0x3f3f3f3f
    #define N 1005
    #define M 100005
    
    using namespace std;
    
    struct Edge
    {
        int y,w,ne;
    }e[M*2],re[M*2];
    
    int x,y,w,n,m,s,t,k;
    int be[N],all;
    int rbe[N],rall;
    int h[N],cnt[N];
    bool vis[N];
    
    struct Point
    {
        int x,g;
        bool operator < (const Point T) const
        {
            return g+h[x]>T.g+h[T.x];
        }
    };
    
    void add(int x, int y, int w)
    {
        e[all].y=y;
        e[all].w=w;
        e[all].ne=be[x];
        be[x]=all++;
    }
    void radd(int x, int y, int w)
    {
        re[rall].y=y;
        re[rall].w=w;
        re[rall].ne=rbe[x];
        rbe[x]=rall++;
    }
    
    void SPFA(int s)
    {
        queue< int > q;
        while(!q.empty())
            q.pop();
        for(int i=0; i<=n; i++)
        {
            h[i]=INF;
            vis[i]=0;
        }
        h[s]=0;
        vis[s]=1;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=rbe[u]; i!=-1; i=re[i].ne)
            {
                int v=re[i].y;
                if(h[v]>h[u]+re[i].w)
                {
                    h[v]=h[u]+re[i].w;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    
    int Astar(int s, int t, int k)
    {
        SPFA(t);
        if(h[s]==INF) return -1;
        priority_queue< Point > q;
        while(!q.empty())
            q.pop();
        memset(vis,0,sizeof(vis));
        memset(cnt,0,sizeof(cnt));
        Point cur,nxt;
        cur.x=s;
        cur.g=0;
        q.push(cur);
        while(!q.empty())
        {
            cur=q.top();
            q.pop();
            if((++cnt[cur.x])>k) continue;
            if(cnt[t]==k)
                return cur.g;
            for(int i=be[cur.x]; i!=-1; i=e[i].ne)
            {
                nxt.x=e[i].y;
                nxt.g=cur.g+e[i].w;
                q.push(nxt);
            }
        }
        return -1;
    }
    
    void init()
    {
        all=0;
        memset(be,-1,sizeof(be));
        rall=0;
        memset(rbe,-1,sizeof(rbe));
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        init();
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d",&x,&y,&w);
            add(x,y,w);
            radd(y,x,w);
        }
        scanf("%d%d%d",&s,&t,&k);
        if(s==t) k++;
        printf("%d
    ",Astar(s,t,k));
        return 0;
    }
    
    /*
    
    2 4
    1 2 1
    1 2 2
    1 2 3
    2 1 5
    1 2 5
    
    */
    View Code
  • 相关阅读:
    关于 拼接 url 连接 参数的问题(爬虫)。
    date 时间确定
    JavaScript跨域解决方法大全
    JS的 try catch使用心得
    博客要搬家啦!
    bzoj 3676: [Apio2014]回文串 -- 回文自动机
    bzoj 2631: tree -- LCT
    bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊 -- LCT
    bzoj 2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 --kdtree
    bzoj 1978: [BeiJing2010]取数游戏 game -- dp
  • 原文地址:https://www.cnblogs.com/Mathics/p/3956140.html
Copyright © 2020-2023  润新知