呵呵😅,一年多没有写文章了。当然,这段时间我也没松懈。闭关了这么长时间回头一看我以前的文章......感觉好尬😓。
好了不多说了开始切入正题:
dij是一种最短路算法,时间复杂度是。
dij的缺点是:不能处理负数。
dij的优点是:复杂度较低、理解起来更容易(个人觉得)。
dij的特点是:比较适合稀疏图。
原理:
给定起点,起点到起点的距离是0,开始以一种类似bfs的方法遍历周围的点(注意要把queue改成priority_queue),如果有更优解就把之前的撤掉改成更优解。
c++代码:
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
struct node{
int v,w;
bool operator<(const node &a)const{
return w>a.w;//重载小于符号(我们想让q从小到大比对所以要把"<"重载为">")
}
};
bool vis[100005]={};//记录是否被访问过
vector<node>g[100005];
priority_queue<node>q;//优先队列
int dist[10005]={};
int main(){
int n,m,s;
cin>>n>>m>>s;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
g[u].push_back({v,w});//建图
}
memset(dist,0x3f,sizeof(dist));//把dist初始化成+∞
q.push({s,0});//以s为起点,遍历整个图
dist[s]=0;//s->s的距离是0
while(!q.empty()){//如果q不空就代表还有东西没完
int x=q.top().v;//当前遍历点为x
q.pop();//q弹出,不然死循环
if(vis[x])continue;//判断是否走过
for(int i=0;i<g[x].size();i++){//遍历x的每一条边
if(dist[g[x][i].v]>dist[x]+g[x][i].w){//如果从这里走更优那就把dist更新(如果vis写在这里就会出很严重的问题——每个点只会遍历一次,无法选择最优解)
dist[g[x][i].v]=dist[x]+g[x][i].w;//更新
q.push({g[x][i].v,dist[g[x][i].v]});//把结果放进去
}
}
}
//输出
for(int i=1;i<=n;i++){
if(dist[i]==0x3f3f3f3f){
cout<<"此路不通"<<endl;
continue;
}
cout<<dist[i]<<endl;
}
return 0;
}