先上至少能用的代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <cmath>
#include <cstring>
using namespace std;
int main() {
int n,t,b,e;
cin>>n>>t>>b>>e; //键入边的个数、点的个数、起点和终点的编号
int list[t+1][t+1]; //创建保存距离用的二维数组
memset(list,-1,sizeof(list));
for (int i = 0; i < n; ++i) { //初始化并且导入边的数据
int a,c,d;
cin>>a>>c>>d;
list[a][c]=list[c][a]=d; //如果是有向图,去掉算式中两个元素中的其中一个就可以
}
vector<pair<pair<int,int>,int>>now;
vector<pair<pair<int,int>,int>>done; //声明两个向量now(存储待处理的距离关系)和done(存储起点到各点的最小值)
done.push_back(make_pair(make_pair(b,b),0)); //初始化done
for (int j = 1; j <= t; ++j) { //初始化now
if(j==b)continue;
now.push_back(make_pair(make_pair(b,j),list[b][j]));
}
while((done.end()-1)->first.second!=e){ //循环查找起点到各点的最小值
int mini = pow(2,30);
int temp;
vector<pair<pair<int,int>,int>>::iterator save;
for(vector<pair<pair<int,int>,int>>::iterator it=now.begin();it!=now.end();it++){
if(it->second!=-1&&it->second<mini){ //查找已知的最小距离并且保存其迭代器和目标点编号
temp=it->first.second;
mini = it->second;
save = it;
}
}
if(mini==pow(2,62))break; //如果now中起点到所有点的距离都为无穷大,则终止查找
done.push_back(*save); //将找到的最小距离和起点与终点编号存入done中
now.erase(save); //从now中将其剔除
for(vector<pair<pair<int,int>,int>>::iterator it=now.begin();it!=now.end();it++){ //更新now中起点到各点的距离
if(list[temp][it->first.second]==-1)continue;//有向图请注意选择的方向
if(it->second==-1)it->second=list[temp][it->first.second]+mini;
else if(it->second>list[temp][it->first.second]+mini)it->second=list[temp][it->first.second]+mini;
}
}
if((done.end()-1)->first.second!=e)cout<<"-1"<<endl; //判断是否找到了起点与终点之间的最短路径,没有则输出-1,有则输出最短距离
else cout<<(done.end()-1)->second<<endl;
return 0;
}
思路
Dijkstra算法的核心在于理解以下这句拗口的又臭又长的话
按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度
以下是我自己的理解:
对于两组顶点集,找出第二组顶点集中的最小点到点距离,将其放入第一组中,并且更新第二组顶点集中点到点的距离(如果该距离小于刚放入第二组点集中的目标点到该目标点的距离加上刚才的最小距离)重复上述步骤。直到第二组点集不可再被更新(其中所有距离皆为无穷大,或为空)或第一组点集中已出现起始点到目标点的最小距离为止。
图论算法第一步Get