dijkstra(堆优化)

dijkstra(堆优化)

算法思想(根据一算法模板实现,仅作记录)

Dijkstra算法采用的是一种贪心的策略,声明一个数组distt来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T(用vis数组来标记),preV存储路径前驱。

  • 初始化,vis[i] = 0, dist[i] = INF,preV[i] = -1。创建一个优先队列q(小顶堆)来存储顶点结点,按dis大小排序。

  • 起始点u入队,dist[u] = 0, vis[u] = 1,然后只要队不空且没找到所有结点的最短路径就一直出队,出队的必是最短的,将其加入集合(置1),然后根据 !vis[j] && dist[j] > temp.dis + c 更新其可达的结点的最短路径。

  • 打印路径需要逆序打印,这里用的递归。

题目链接

/*==================================================*\
 | Dijkstra O(E * log E) 
 | INIT: 调用init(nv, ne)读入边并初始化;
 | CALL: dijkstra(nv, u, adj); dist[i]为u到i的最短距离
\*==================================================*/
#include<bits/stdc++.h>
using namespace std;

#define typec int // type of cost
#define E 100000    //边数
#define V 1000      //顶点数

const typec inf = 0x3f3f3f3f; // max of cost

typec dist[V]; 
int vis[V], preV[V]; 

struct node { 	//顶点结点,v:顶点号, dis:距离源点的最短路径
    int v; 
    typec dis; 
    node (int _v = 0, typec _dis = 0) : v(_v), dis(_dis) {} 
    bool operator < (const node& r) const { 
        return dis > r.dis; 
    } 
};
struct edge{	//边表节点
    int v;
    typec c;
    edge (int _v = 0, int _c = 0) : v(_v), c(_c) {}
};

void dijkstra(int nv, const int u, vector<edge> *adj){ 
    priority_queue<node> q;  
    q.push(node(u, 0));
    vis[u] = 1;
    dist[u] = 0; 
    int cnt = 0;
    while (!q.empty() && cnt <= nv){
        node temp = q.top();
        q.pop();
        vis[temp.v] = 1;	//已经求得的最短路径的顶点号置1
        cnt++;
        for (int i = 0; i < adj[temp.v].size(); i++){
            int j = adj[temp.v][i].v;
            typec c = adj[temp.v][i].c;
            if (!vis[j] && dist[j] > temp.dis + c){	//由新求得最短路径的点temp.v更新其可达的点的最短路径
                q.push(node(j, temp.dis+c));
                dist[j] = temp.dis + c;
                //preV[j] = temp.v;         //保存路径
            }
        }
    }
   

} 

inline void addedge(int u, int v, typec& c, vector<edge> *adj){ 
    adj[u].push_back(edge(v, c));
    adj[v].push_back(edge(u, c)); //无向图
} 

void init(int nv, int ne, vector<edge> *adj){ 
    memset(vis, 0, sizeof(vis));
    //memset(preV, -1, sizeof(preV)); 
    for (int i = 0; i < nv; i++) 
        dist[i] = inf; 
    for (int i = 0; i < ne; ++i) { 
        int u, v;
        typec c;
        cin >> u >> v >> c;    
        addedge(u-1, v-1, c, adj);               // vertex: 0 ~ n-1, 单向边
    } 
}

void print(int k){		//打印路径
    if (-1 != k){
        print(preV[k]);
        cout << k << ' ';
    }
}

void output(int k){
    cout << dist[k] << endl; 
    //print(k);     //打印路径
    //cout << endl;
}
int main(){
    int nv, ne;
    while(cin >> nv >> ne){
        if(nv == 0 && ne == 0)
            return 0;
        vector<edge> adj[nv];
        init(nv, ne, adj);
        dijkstra(nv, 0, adj);
        //for (int i = 0; i < nv; i++)
            //output(i);
        output(nv-1);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值