整体来看dij就是从起点开始扩散致整个图的过程,为什么说他稳定呢,是因为他每次迭代,都能得到至少一个结点的最短路。(不像SPFA,玄学复杂度)
但是他的缺点就是不能处理带负权值的边,和代码量稍稍复杂。
dij算法(采用方法邻接表+优先队列优化)复杂度O(mn)降为O(mlogn)
不多哔哔,我们直接看图解:
核心:每次去往距离起点最近的那个点,并且是第一次访问
图中用黄色来标记哪些点已经走过。
之前刷过几个dij的图论题,有兴趣的可以去我的博客看一下图论刷水题记录(一)(最短路-----dijkstra算法)
本来没打算写这个算法详解,但是上导论课的时候老师提到过,还要做作业,所以要写就写的详细一点吧,直接用老师的图来进行说明
手动模拟一下算法过程:
1.我们设置一个数组dis[20]用来储存到达该点距离的最小值(实时状态),并且初始化他们的值为无穷大。
2.从起点出发,标记起点,因为自己到自己的距离为0,所以v1->v1=0,更新v1的临边,更新好后如图所示:
3.找到距离起点最近的点(如下图),并且更新他的临边,我们发现从此点到上方的点距离要小于之前更新过的值,故我们将7更新为6,并将此点右边的点更新为5.
4.我们继续进行上述操作,找到距离起点最近的点,标记为走过,更新他的临边,我们发现从此点到他左上方的点要比之前更新过的值小,故将左上方点更新为8,并将他上方和右上方的点分别更新为16和14
5.继续在未走过的点中寻找距离起点最短的点,发现是6,将其标记为走过,我们发现它可以往正上方去走,但是问题是8小于5+6,所谓不更新该点
6.找到距离起点最短的点,标记该点,发现它可以去他右边这个点,并且8+5小于16,所以更新该点的值为13.
7.找到距离起点最短的点,标记该点,发现没有可以更新的点。
8.找到距离起点最短的点,标记该点,发现没有可以更新的点。
全图点均已标记算法结束
经过以上的步骤,我们可以求出所有的点距离起点的最短路
ps(外带一个用邻接表+优先队列优化过的程序)
#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <math.h>
#include <string>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 2010
//#define true false
//#define false true
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
const double pi = acos(-1);
typedef long long ll;
const int mod = 1e9 + 7;
using namespace std;
int t,n;
bool visited[maxn];
int dis[maxn];
struct wazxy{
int v,val;
wazxy(int v1,int e1){v=v1;val=e1;}
};
vector<wazxy> a[maxn];
struct node{
int id,dis;
node(int a,int b){id=a,dis=b;}
bool operator < (const node & a)const
{return dis>a.dis;}
};
void dij(){
int s=1;
dis[s]=0;
priority_queue<node>q;
q.push(node(s,dis[s]));
while(!q.empty()){
node temp=q.top();
q.pop();
if(visited[temp.id]) continue;
visited[temp.id]=true;
for(int i=0;i<a[temp.id].size();i++){
wazxy node1=a[temp.id][i];
if(visited[node1.v]) continue;
if(dis[node1.v]>node1.val+temp.dis){
dis[node1.v]=node1.val+temp.dis;
q.push(node(node1.v,dis[node1.v]));
}
}
}
printf("%d",dis[n]);
}
int main()
{
cin>>t>>n;
memset(visited,false,sizeof(visited));
memset(dis,MaxN,sizeof(dis));
while(t--){
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
a[x].push_back(wazxy(y,v));
}
dij();
return 0;
}