• 【POJ 3255】(dijkstra优化,次最短路)


    题意:求 1 - n 的次最短路

    分析:

      先来谈谈Dijkstra的优化。对于每次寻找到当前为访问过的点中距离最短的那一个,运用优先队列进行优化,避免全部扫描,每更新一个点的最短距离就加入优先队列。有人会问,一个点如果已经处理完成了,那它还留在队列中怎么办?我们放入队列时将一个点那时的顶点编号和最短距离进行打包,如果取出该点时,它当前的最短距离小于该点标记的最短距离,说明该点已经取到最短距离,不进行操作。或者直接用一个vis数组来记录某一个点是否已经取到最短距离;其次的优化是用邻接表存储与每一个点相连的所有边,方便处理。

      这道题的做法和最短路径基本一致,唯一的不同点在于,在求出最短路径的情况下必须要保留下次短路径。对于Dijkstra判断中取出的每一个点,如果到它的最短距离大于当前该点的次短距离,则当前该点已经取到最短距离和次短距离,不进行操作,否则进行两次判断:如果小于最短边,则赋给最短边

    #include <iostream>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <stdio.h>
    #include <cmath>
    #include <string.h>
    #include <vector>
    
    #define ll long long
    using namespace std;
    
    const int inf = 0x3f3f3f3f;
    ll d[5050], d2[5050];
    struct edge{
        int u, v, w, next;
    }e[200100];
    int head[5050], visit[5050], cnt, n, r;
    struct node
    {
        int id;
        ll dist;
        node(int _id = 0, ll _dist = 0) : id(_id), dist(_dist){}
        bool operator < (const node & x) const
        {
            return dist > x.dist;
        }
    };
    
    void add(int u, int v, int w)
    {
        e[cnt].u = u;
        e[cnt].v = v;
        e[cnt].w = w;
        e[cnt].next = head[u];
        head[u] = cnt++;
    }
    
    void dij()
    {
        for(int i = 0; i <= n; i++)
            d[i] = d2[i] = inf;
        priority_queue<node> q;
        while(!q.empty())
            q.pop();
        d[1] = 0;
        q.push(node(1, 0));
        node p;
        while(!q.empty())
        {
            p = q.top();
            q.pop();
            int u = p.id;
            ll dis = p.dist;
            if(d2[u] < dis)
                continue;
            for(int i = head[u]; i != -1; i = e[i].next)
            {
                int v = e[i].v;
                ll dd = dis + e[i].w;
                if(d[v] > dd)
                {
                    swap(d[v], dd);
                    q.push(node(v, d[v]));
                }
                if(d2[v] > dd && dd > d[v])
                {
                    d2[v] = dd;
                    q.push(node(v, d2[v]));
                }
            }
        }
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        int u, v, w;
        cnt = 0;
        memset(head, -1, sizeof(head));
        scanf("%d%d", &n, &r);
        for(int i = 0; i < r; i++)
        {
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w);
            add(v, u, w);       
        }
        dij();
        printf("%lld
    ", d2[n]);
        return 0;
    }
    

      

    ,并将最短边赋给次短边;或者如果大于最短变且小于次短边,则赋给次短边。两次完成之后均要加入队列

  • 相关阅读:
    URL传递中文:Server.UrlEncode与Server.UrlDecode
    面向对象的封装性和多态性
    C#虚基类继承与接口的区别
    C# String与string的区别
    C# 索引器的使用
    ASP.NET 页面之间传递值的几种方式
    SQL Server中的游标CURSOR
    OpenLayers中的图层(转载)
    OpenLayers介绍和第一个例子(转载)
    SQL笔记-第七章,表连接
  • 原文地址:https://www.cnblogs.com/zxybdnb/p/11576109.html
Copyright © 2020-2023  润新知