• dijkstra算法的堆优化


    普通的dijkstra算法模板:

    //数据结构
    int g[LEN][LEN];    //邻接矩阵 
    int vis[LEN];        //标记是否访问
    int dist[LEN]         //源点到各点的距离
    
    fill(dist,dist+LEN,MAX);
    dist[s]=0;
    while(1){
        int u=-1,d=MAX;
        for(int i=0;i<N;i++){
            if(!vis[i] && dist[i]<d){
                d=dist[i];
                u=i;
            }
        }
        if(u<0) break;
        vis[u]=1;
        for(int i=0;i<N;i++) if(!vis[i]){
            if(dist[u]+g[u][i]<dist[i]){
                dist[i]=dist[u]+g[u][i];
            }
        }
    } 

    为了能在“取出最小的dist”这一步实现优化,我们使用priority_queue进行优化。下面用cmp结构体重载括号运算符priority_queue进行改造:

    struct cmp{
        bool operator () (int a,int b){
            return dist[a]>dist[b];
        }
    };
    priority_queue<int,vector<int>,cmp> pq;

    然后我们来看堆优化的dijkstra算法:

    //数据结构
    int g[LEN][LEN];    //邻接矩阵 
    int vis[LEN];        //标记是否访问
    int dist[LEN]         //源点到各点的距离
    struct cmp{
        bool operator () (int a,int b){
            return dist[a]>dist[b];
        }
    };
    priority_queue<int,vector<int>,cmp> pq;
    
    fill(dist,dist+LEN,MAX);
    dist[s]=0;
    pq.push(s);
    while(!pq.empty()){
        int u=pq.top();
        pq.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=0;i<N;i++) if(!vis[i]){
            if(dist[u]+g[u][i]<dist[i]){
                dist[i]=dist[u]+g[u][i];
                pq.push(i);
            }
        }
    } 

    加粗的代码是未优化dijkstra所没有的。

    每次更新结点,都把新的结点存到优先队列中去。

    用一道例题练手。OJ链接:Travel Plan

    AC代码:

    #include <stdio.h>
    #include <memory.h>
    #include <math.h>
    #include <string>
    #include <vector>
    #include <set>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <map>
    
    #define I scanf
    #define OL puts
    #define O printf
    #define F(a,b,c) for(a=b;a<c;a++)
    #define FF(a,b) for(a=0;a<b;a++)
    #define FG(a,b) for(a=b-1;a>=0;a--)
    #define LEN 1010
    #define MAX (1<<30)-1
    #define V vector<int>
    
    using namespace std;
    
    int g_dist[LEN][LEN];
    int g_cost[LEN][LEN];
    int vis[LEN];
    int dist[LEN];
    int cost[LEN];
    int pre[LEN];
    
    struct cmp{
        bool operator () (int a,int b){
            return dist[a]>dist[b];
        }
    };
    priority_queue<int,vector<int>,cmp> pq;
    
    int main(){
    //    freopen("1030.txt","r",stdin);
        int n,m,s,e,i,j,a,b,c,d,t;
        I("%d%d%d%d",&n,&m,&s,&e);
        fill(g_dist[0],g_dist[0]+LEN*LEN,MAX);
        FF(i,m){
            I("%d%d%d%d",&a,&b,&c,&d);
            g_dist[a][b]=c;
            g_dist[b][a]=c;
            g_cost[a][b]=d;
            g_cost[b][a]=d;
        }
        fill(dist,dist+LEN,MAX);
        fill(cost,cost+LEN,MAX);
        cost[s]=0;
        pre[s]=-1;
        //加入堆优化 
        pq.push(s);    //源点入队 
        dist[s]=0;
        while(!pq.empty()){
            int u=pq.top();
            pq.pop();
            if(vis[u]) continue;
            vis[u]=1;
            FF(i,n) if(!vis[i]){
                if(dist[u]+g_dist[u][i]<dist[i] || (dist[u]+g_dist[u][i]==dist[i] && cost[u]+g_cost[u][i]<cost[i])){
                    dist[i]=dist[u]+g_dist[u][i];
                    cost[i]=cost[u]+g_cost[u][i];
                    pre[i]=u;
                    //如果通过u点更新了一个i点,那么i点入队。
                    pq.push(i);
                }
            }
        }
        vector<int> path;
        i=e;
        while(i!=-1){
            path.insert(path.begin(),i);
            i=pre[i];
        }
        FF(i,path.size()) O("%d ",path[i]);
        printf("%d %d
    ",dist[e],cost[e]) ;
        return 0;
    }
  • 相关阅读:
    打sql server pack4后打开网站报错的解决办法
    北京大学的三角形文章
    一次SQL Server 2000修复实践的说明
    今天重看了几集《将爱情进行到底》
    MakeFile的写法
    [经验杂谈]与大虾对话:领悟设计模式zz
    论函数调用约定(zz)
    用标准模板库STL实现文件比较(zz)
    C++中的虚函数(virtual function)
    为学院科研办做的个小应用管理程序
  • 原文地址:https://www.cnblogs.com/TQCAI/p/8545162.html
Copyright © 2020-2023  润新知