• 【A*/K短路】 [USACO08MAR]Cow Jogging G


    P2901 [USACO08MAR]Cow Jogging G

    思路:先反向建边求各点到节点1的最短路,再A*依次得到节点(n)到节点(1)的第(k)短路。

    总体来说就是改进版的BFS,在BFS的基础上另外设定了一个估价函数作为节点出队顺序的依据,而不像BFS那样先入队者先出队。在本题中,估价最小的节点会被优先拓展,然后是次小的、更小的……每次拓展到终点(1)时,都形成一条通路,越先形成的通路越短。

    const int INF = 0x3f3f3f3f;
    const int maxn = 1e4 + 100;
    
    inline int read() {
        int X = 0, w = 0; char ch = 0;
        while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
        while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
        return w ? -X : X;
    }
    
    int n, m, k;
    int d[1100];
    //各点到池塘的距离
    bool done[1100];
    int ahead[1100], anum = 0;
    int head[1100], num = 0;
    
    struct Edge {
        int next, to, dis;
    }ae[maxn],e[maxn];
    
    struct Heapnode {
        int u, dis;
        bool operator < (const Heapnode& t) const {
            return dis > t.dis;
        }
        Heapnode(int from, int d) :u(from), dis(d) {}
    };
    
    struct node {
        int pos, dis;
        //dis为 起点到pos的最短距离
        bool operator <(const node& t)const {
            return dis + d[pos] > t.dis + d[t.pos];
            //加上点pos到终点的估计距离来比较,总估值最小的优先
        }
        node(int u, int d) :pos(u), dis(d) {}
    };
    
    void addedge1(int from, int to, int dis) {
        anum++;
        ae[anum].next = ahead[from];
        ae[anum].to = to;
        ae[anum].dis = dis;
        ahead[from] = anum;
    }
    
    void addedge2(int from, int to, int dis) {
        num++;
        e[num].next = head[from];
        e[num].to = to;
        e[num].dis = dis;
        head[from] = num;
    }
    
    void dij(int s) {
        priority_queue<Heapnode> pq;
        d[s] = 0;
        pq.push(Heapnode(s,d[s]));
        while (pq.size()) {
            Heapnode tmp = pq.top(); pq.pop();
            int u = tmp.u;
            if (done[u]) continue;
            for (int i = ahead[u]; i; i = ae[i].next) {
                if (d[u] + ae[i].dis < d[ae[i].to]) {
                    d[ae[i].to] = d[u] + ae[i].dis;
                    pq.push(Heapnode(ae[i].to, d[ae[i].to]));
                }
            }
            done[u] = true;
        }
    }
    
    int Astar(int k) {
        priority_queue<node> Q;
        Q.push(node(n, 0));
        while (Q.size()) {
            int u = Q.top().pos;
            int dis = Q.top().dis;
            Q.pop();
            //取到终点
            if (u == 1) {
                k--;
                cout << dis << endl;
                if (!k) return 0;
                //前k短路已经全部求出
            }
            for (int i = head[u]; i; i = e[i].next) {
                int v = e[i].to, w = e[i].dis;
                Q.push(node(v, w + dis));
                //w是点u到点v的距离 
                //dis是起点到点u的距离
                //w+dis是起点到点v的距离
            }
        }
        //要计算前k短路,但可能只能算出前a短路,剩下的不存在
        //优先队列为空时能计算的前a短路已经算完
        //剩下的k-a行只能输出-1
        return k;
    }
    
    
    int main() {
        n = read();m = read();k = read();
        memset(d, INF, sizeof(d));
        memset(done, false, sizeof(done));
        for (int i = 1; i <= m; i++) {
            int u, v, dis;
            u = read(); v = read(); dis = read();
            addedge1(v, u, dis);
            //反向建边存图来求各点到终点的最短路
            addedge2(u, v, dis);
            //正常建边存图来Astar
            //注意别存成了双向边
        }
        dij(1);
        int last = Astar(k);
        while (last--) cout << -1 << endl;
        return 0;
    }
    
  • 相关阅读:
    Linux下端口被占用确认
    Debuggex – 超好用的正则表达式可视化调试工具
    URL最大长度
    无需重启 修改计算机名直接生效
    UDP穿越NAT原理(p2p)
    gdb中信号
    锁 (读写锁优先级 写饥饿) (锁竞争引发的高系统调用)
    Loopback接口用途---用作管理地址。
    C/C++调试:gdbserver的简单使用
    总结一下NDK crash排查步骤
  • 原文地址:https://www.cnblogs.com/streamazure/p/13713676.html
Copyright © 2020-2023  润新知