Dijkstra算法介绍
算法特点:
迪杰斯特拉算法可以算出从一个顶点到其余各顶点的最短路径,解决的是有权图中最短路径问题
Dijkstra算法思路
迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
Dijkstra算法的模板题,采用贪心的策略,每次遍历与起始点最近且未被访问,同时权值还是最小的点
找到这个点后,将这个点进行标记(说明起始点到该点的距离已经是最短了)
然后从该点进行拓展延伸,比较当前拓展的值与拓展之前的权值的大小,取最小值
然后继续拓展,直到拓展到终点结束
朴素代码及讲解
#include <bits/stdc++.h>
#define lowbit(x) ((x)&(-x))
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
int st[10100],d[10100],m,n,s;
vector<PII>vt[500100];
void dis(int u)
{
for(int i=1;i<=m;i++)
{
int v=0;
for(int j=1;j<=m;j++)
{
if(st[j]!=1&&d[j]<d[v])
v=j;
}
st[v]=1;
for(auto x:vt[v])
{
int a=x.first,b=x.second;
if(d[a]>d[v]+b)
d[a]=d[v]+b;
}
}
}
signed main()
{
IOS
cin>>m>>n>>s;
for(int i=1;i<=n;i++)
{
int u,v,w;
cin>>u>>v>>w;
vt[u].push_back({v,w});
}
int t=pow(2,31)-1;
for(int i=0;i<=m;i++)
d[i]=t;
d[s]=0;
dis(s);
for(int i=1;i<=m;i++)
cout<<d[i]<<" ";
return 0;
}
注:不能解决负边权问题
优化代码及讲解
#include <bits/stdc++.h>
#define lowbit(x) ((x)&(-x))
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
int st[100100],d[100100],m,n,s;
vector<PII>vt[500100];
priority_queue<PII>q;
void dis(int u)
{
q.push({0,u});
while(q.size())
{
PII t=q.top();
q.pop();
int v=t.second;
if(st[v])continue;
st[v]=1;
for(auto x:vt[v])
{
int a=x.first,b=x.second;
if(d[a]>d[v]+b)
{
d[a]=d[v]+b;
q.push({-d[a],a});
}
}
}
}
signed main()
{
IOS
cin>>m>>n>>s;
for(int i=1;i<=n;i++)
{
int u,v,w;
cin>>u>>v>>w;
vt[u].push_back({v,w});
}
int t=pow(2,31)-1;
for(int i=0;i<=m;i++)
d[i]=t;
d[s]=0;
dis(s);
for(int i=1;i<=m;i++)
cout<<d[i]<<" ";
return 0;
}