Dijkstra算法——计算一个点到其余全部点的最短路径的算法

迪杰斯特拉算法百度百科定义:传送门html

gh大佬博客:传送门node

迪杰斯特拉算法用来计算一个点到其余全部点的最短路径,是一种时间复杂度相对比较优秀的算法 O(n2)(相对于Floyd算法来讲)ios

是一种单源最短路径算法,可是它并不能处理负边权的状况算法

Dijkstra的算法思想:①将一开始全部的非源点到源的距离设置成无限大(你认为的无限大其实是0x3f(int)或者0x7fffffff(long long)),而后源到源距离设置成0(不就是0吗),而后每次找到一个距离源最短的点u,将其变成白点,枚举全部的蓝点,若是源到白点存在中转站——一个蓝点使得源->蓝点和蓝点->白点的距离和更短,就更新。②每找到一个白点,就尝试更新其余蓝点,直到更新完毕。数组

代码及注释:优化

#include<cstdio> #include<iostream> #include<cstdlib> #include<iomanip> #include<cmath> #include<cstring> #include<string> #include<algorithm> #include<time.h> #include<queue>
using namespace std; typedef long long ll; typedef long double ld; typedef pair<int,int> pr; const double pi=acos(-1); #define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define Rep(i,u) for(int i=head[u];i;i=Next[i])
#define clr(a) memset(a,0,sizeof a)
#define pb push_back
#define mp make_pair
#define fi first
#define sc second ld eps=1e-9; ll pp=1000000007; ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} ll read(){ ll ans=0; char last=' ',ch=getchar(); while(ch<'0' || ch>'9')last=ch,ch=getchar(); while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); if(last=='-')ans=-ans; return ans; }//快读 //head



const int maxn=5001; int g[maxn][maxn];//g数组用来存储图; 
int n,m,s;//分别表示点的个数、有向边的个数、出发点的编号;
bool vis[maxn];//表示是否已经到达过;
int d[maxn];//d[i]表示从询问点到点i的最短路径;
const int inf=2147483647; int main () { n=read(),m=read(),s=read(); rep(i,1,n) { d[i]=inf; rep(j,1,n) g[i][j]=inf; g[i][i]=0;//本身到本身的最短路径固然是0 
    }//初始化数组; 
 rep(i,1,m) { int u=read(),v=read(),w=read(); //u,v,i分别表示第i条有向边的出发点、目标点和长度;
        g[u][v]=w;//读入; 
 } vis[s]=1;//将起点标记成已经到达;
 rep(i,1,n) d[i]=g[s][i];//将最短路径初始化; //若是两点之间有路线就初始化为该距离,若是没有就仍是inf;
        
    while(1) { int stt_node=0,stt_dis=inf;//stt=shortest 初始化两个变量 // stt_node表示最短路径的终点,stt_dis表示最短路径的长度 
 rep(i,1,n) { if(vis[i]==0&&d[i]<stt_dis) //若是该点尚未到达,而且他的距离小于最短距离 
 { stt_node=i,stt_dis=d[i];//更新变量 
 } } if(stt_node==0) break; //若是已经没有能够更新的最短路径了,就说明已经结束了
 vis[stt_node]=1;//将该点标记成已经到达 
 rep(i,1,n) { if(vis[i]||g[stt_node][i]==inf)continue; //若是并无到达或者是两点之间没有路径,就进入下一层循环 
 d[i]=min(d[i],stt_dis+g[stt_node][i]);//更新最短路径 
 } } rep(i,1,n) printf("%d ",d[i]); return 0; }

咱们考虑一下对它的优化。由于若是咱们每一次都要扫一遍判断出边,咱们还不如直接存出边:spa

邻接表!(链式前向星)

#include<cstdio> #include<iostream> #include<cstdlib> #include<iomanip> #include<cmath> #include<cstring> #include<string> #include<algorithm> #include<time.h> #include<queue>
using namespace std; typedef long long ll; typedef long double ld; typedef pair<int,int> pr; const double pi=acos(-1); #define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define Rep(i,u) for(int i=head[u];i;i=Next[i])
#define clr(a) memset(a,0,sizeof a)
#define pb push_back
#define mp make_pair
#define fi first
#define sc second ld eps=1e-9; ll pp=1000000007; ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} ll read(){ ll ans=0; char last=' ',ch=getchar(); while(ch<'0' || ch>'9')last=ch,ch=getchar(); while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); if(last=='-')ans=-ans; return ans; }//快读 //head


const ll INF = 2147483647; struct edge { ll to, dis_, next; } Edge[9999999]; struct node { ll to, dis; inline friend bool operator<(const node &a, const node &b) { return a.dis < b.dis; } }; ll head[9999999], dis[9999999]; bool vst[9999999]; ll nodenum, edgenum, origin_node, cnt = 1, t; priority_queue<node> q; inline void add_edge(ll from, ll to, ll value) { Edge[cnt].to = to; Edge[cnt].dis_ = value; Edge[cnt].next = head[from]; head[from] = cnt++; } inline void dijkstra() { for (register int i = 1; i < origin_node; i++) { dis[i] = INF; } //dis[origin_node]=0;
    for (register int i = origin_node + 1; i <= nodenum; i++) { dis[i] = INF; } q.push((node){origin_node, 0}); while (!q.empty()) { int x = q.top().to; q.pop(); if (vst[x]) continue; vst[x] = 1; for (register int i = head[x]; i; i = Edge[i].next) { dis[Edge[i].to] = min(dis[Edge[i].to], dis[x] + Edge[i].dis_); q.push((node){Edge[i].to, dis[Edge[i].to]}); } } } int main() { nodenum = read(), edgenum = read(), origin_node = read() ;//t=read();
    for (register int i = 1; i <= edgenum; i++) { register int f, t, v; f = read(), t = read(), v = read(); add_edge(f, t, v); } dijkstra(); rep(i,1,nodenum) { printf("%lld ",dis[i]); } return 0; }
相关文章
相关标签/搜索