三者不同,就我个人理解而言,迪杰斯特拉是求单源点最短路径且权值为非负,算法效率为:;弗洛伊德算法是求任意两点间的最短路径,算法复杂度高,为;SPFA为单源点最短路径,权值可为负数,时间复杂度为;三者均可以处理有向和无向图。
且我觉得你只要会了SPFA,另外两种都可以解决,SPFA既可以求负值也可以求解正的权值,再多加一层for循环那么弗洛伊德求任意亮点最短路径也可以解决。
1.SPFA
第一种写法:vector+结构体
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
struct node{
int v,weight;
};
vector<node> V[MAX]; //二维动态数组
int vis[MAX],dis[MAX]; //dis[i]用以存储源点dao点i的最短路径 vis[i]为点i是否在队列中
void SPFA(int src){
queue<node> q;
q.push_back(src);
vis[src]=1;
dis[src]=0;
while(!q.empty())
{
int t=q.front();
q.pop();
vis[t]=0;
for(int i=0;i<V[t].size();i++)
{
if(dis[t]+V[t][i].weight<dis[V[t][i].v])
{
dis[V[t][i].v]=dis[t]+V[t][i].weight;
if(!vis[V[t][i].v])
{
vis[V[t][i].v]=1;
q.push_back(V[t][i].v);
}
}
}
}
}
int main() {
int n,s,t; //分别表示n个节点,s为源点,t为终点
memset(dis,INF,sizeof dis);
for(int i=0;i<n;i++)
{
int u,v,w;
cin>>u>>v>>w;
node t;
t.v=v;
t.weight=w;
V[u].push_back(t);
t.v=u;
V[u].push_back(t); //两个同时push表明为无向图 若有向图只push一个值即可
}
SPFA(s);
cout<<dis[t];
return 0;
}
第二种写法:vector+pair,基本差不多,看起来会简洁一些
#include<bits/stdc++.h>
using namespace std;
const int MAX = 1e5+10;
const int INF=0x3f3f3f3f;
typedef pair<int,int> PII;
vector<PII> V[MAX];
int d[MAX],vis[MAX];
void SPFA(int src)
{
memset(d,INF,sizeof d);
queue<int> q;
q.push(src);
vis[src]=1;
d[src]=0;
while(!q.empty())
{
int t=q.front();
q.pop();
vis[t]=0;
for(auto k:V[t])
{
if(d[t]+k.second<d[k.first])
{
d[k.first]=d[t]+k.second;
if(!vis[k.first])
{
vis[k.first]=1;
q.push(k.first);
}
}
}
}
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
V[u].push_back({v,w});
}
SPFA(1);
if(d[n]==INF)
cout<<-1;
else
cout<<d[n];
}
2.Dijkstra
vector+堆优化
#include<bits/stdc++.h>
using namespace std;
const int MAX = 1e5+10;
const int INF=0x3f3f3f3f;
typedef pair<int,int> PII;
vector<PII> V[MAX];
int d[MAX],vis[MAX];
void Dijkstra()
{
memset(d,INF,sizeof d);
priority_queue<PII,vector<PII>,greater<PII>> q;
q.push({0,1});
d[1]=0;
while(!q.empty())
{
PII t=q.top();
q.pop();
int ver=t.second;
for(auto k:V[ver])
{
int j=k.first,w=k.second;
if(d[ver]+w<d[j])
{
d[j]=d[ver]+w;
q.push({d[j],j});
}
}
}
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
V[u].push_back({v,w});
}
Dijkstra();
if(d[n]==INF)
cout<<-1;
else
cout<<d[n];
}
3.弗洛伊德
DP可以解决,复杂度较高
#include <bitsdc++.h>
using namespace std;
const int N = 210, INF = 0x3f3f3f3f;
int d[N][N];
int n, m, k;
int main() {
scanf("%d%d%d", &n, &m, &k);
memset(d, 0x3f, sizeof d);
for(int i=1; i<=n; i++) d[i][i] = 0;
for(int i=0; i<m; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
d[a][b] = min(d[a][b], c);
}
for(int k=1; k<=n; k++) {
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
while(k--) {
int a, b;
scanf("%d%d", &a, &b);
if(d[a][b] >= INF/2) cout << "impossible" << endl;
else cout << d[a][b] << endl;
}
return 0;
}