一、简介
(1)寻找扩展顶点的步骤可用堆来优化,即利用堆的特性:根顶点始终为最值,来动态维护图中节点到目的顶点距离(边权)的变化。
二、代码
/*
寻找扩展顶点,利用堆优化
*/
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef pair<int,int> P;//fisrt:边权,second:目的顶点编号
#define MAXV 1000
#define Inf 0x3f3f//>16000
int V,E;//顶点数,边数
int s,ed;//起点,终点
int cost[MAXV][MAXV];//cost[u][v] 边(u,v)的边权
int d[MAXV];//d[i]表示顶点i到起点的最短路径
int per[MAXV];
int vis[MAXV];//vis[i]标记顶点i是否已求得到起点的最短路径 ,是:1.否:0
//迪杰斯特拉算法
void djks(){
d[s]=0;
int v,u;
priority_queue<P,vector<P>, greater<P> > pq;//小根堆 ,按pair.first比较
pq.push({0,s});
while(!pq.empty()){
P p=pq.top();
pq.pop();
v=p.second;
if(d[v]<p.first) continue;//顶点v已更新最短路,取出
vis[v]=1;//扩展顶点v
for(u=1;u<=V;++u)//以顶点v为中间节点去更新其他点到s的最短路
if(!vis[u]&&d[u]>d[v]+cost[v][u])
d[u]=d[v]+cost[v][u],per[u]=v,pq.push({d[u],u});
}
}
//打印路径
void printPath(int v,int ed){
if(v==ed){
cout<<v<<" ";
return;
}
printPath(per[v],ed);
cout<<v<<" ";
}
int main(){
memset(vis,0,sizeof(vis));
fill(d,d+MAXV,Inf);
fill(cost[0],cost[0]+MAXV*MAXV,Inf);
cin>>V>>E;
int u,v,w;
for(int i=0;i<E;++i){//输入E条边
cin>>u>>v>>w;
cost[u][v]=cost[v][u]=w;
}
cin>>s>>ed;//起点、终点
djks();
cout<<d[ed]<<endl;
printPath(ed,s);
return 0;
}