注意:Dijkstra算法只适用于边权为非负值的带权图
时间复杂度为O(m*log n)级别
主要思路:(采用STL中的优先队列进行优化)
准备工作:先用vector容器开适当大小的数组存放与每个点相连点的位置与边权(用pair类型成对存放),创建dis[N]来存放所有点到起始点的距离,并将所有点到起始点的距离初始化为INF(int范围内最大的数),以便后续更新最短距离。创建vis[N]来标记某个点是否被更新过。
将某点的编号和该点当前到起始点最短距离存入队列(假设点1为起始点,点1到1的最短距离为0,那么将存入(1,0)),当队列不为空时选出堆顶元素(以下操作一直循环到队列为空),用该点(假设为点u)的位置带入vector容器遍历与点u相连的点(假设为点v),如果dis[v]>dis[u]+边u-v的边权(用w表示),就将dis[v]更新为dis[u]+w;最后再把(v,dis[v])存入队列即可。
完整代码如下:
#includeusing namespace std; const int N=1e5; const int INF=1e9; int dis[N]; bool vis[N]; vector >g[N]; struct note{ int id;//点的位置 int d;//该点到起始点的最短距离 }; bool operator<(note a,note b){//重载小于号运算符,让堆元素从小到大排列 return a.d>b.d; } priority_queue que; int n,m,u,v,w; Dijkstra(int st){ for(int i=1;i<=n;i++){ vis[i]=0,dis[i]=INF;//初始化 } dis[st]=0; que.push({st,0}); while(!que.empty()){ note t=que.top();que.pop();//每次取出堆顶元素后弹出该元素 int u=t.id; if(vis[u]) continue;//如果已经被更新过就跳过该点 vis[u]=1; for(auto eg:g[u]){//遍历与点u相邻的所有点 int v=eg.first; int w=eg.second; if(dis[v]>dis[u]+w) dis[v]=dis[u]+w; que.push({v,dis[v]}); } } } int main(){ cin>>n>>m; for(int i=1;i<=m;i++){ cin>>u>>v>>w; g[u].push_back({v,w}); } int st;cin>>st; Dijkstra(st); for(int i=1;i<=n;i++){ cout< "<



