迪杰斯特拉优化版本:vector + 优先队列
△迪杰斯特拉算法的核心:每次找距离s点最短的元素 + 松弛操作
①要用优先队列取出最短距离降低时间复杂度,用veotor减少空间
②定义一个pair类型,作为优先队列的元素。typedef pair<int , int > P ,first是距离,second是边的终点
③pair类型作为优先队列的元素时,默认排序是先排序first,后再排序second。(升序)
因此,距离是first,边的终点是second,不可调换
#include <stdio.h> #include <queue> #include <string.h> #define MAX 100 using namespace std; typedef pair<int,int> P; //first:dis[i] second:下标i,边的终点 vector<P> map[MAX]; //不能先下标后权值,因为pair先排序first后排序second int vis[MAX]; int dis[MAX]; priority_queue<P, vector<P>, greater<P> > q; const int INF = 0x3f3f3f3f; void Dijkstra(int s, int n){ memset(dis,INF,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[s]=0; q.push(P(0,s)); //将起始点push入队列 while(!q.empty()){ P p =q.top(); //每次取最小元素 q.pop(); //出队 int u=p.second; if(vis[u]) continue; vis[u]=1; for(int i=0;i<map[u].size();i++){ //i并不是边的终点,只是顺序存储的东西 int v=map[u][i].second; //获取边的终点v int w=map[u][i].first; //获取u到v的距离 if(!vis[v]){ if(dis[v]>dis[u]+w){ dis[v]=dis[u]+w; q.push(P(dis[v],v)); //松弛操作过的元素入队 } } } } } int main(){ int n,m,s; int u,v,w; while(scanf("%d %d %d",&n,&m,&s)!=EOF){ //顶点数n, 边数m, 起始点s for(int i=1;i<=n;i++) map[i].clear(); //清空vector 注意 vector 不能用二维数组初始化 for(int i=0;i<m;i++){ scanf("%d %d %d",&u,&v,&w); map[u].push_back({w,v}); //无向图 map[v].push_back({w,u}); //有向图只push一次 } Dijkstra(s,n); for(int i=1;i<=n;i++) printf("%d ",dis[i]); } return 0; }
原文地址:https://www.cnblogs.com/shiliuxinya/p/12180782.html
时间: 2024-10-05 05:04:59