floyed
- 核心代码
for (i = 1; i <= n; i++){
for (j = 1; j <= n; j++){
if (e[i][j] > e[i][1] + e[1][j])
e[i][j] = e[i][1] + e[1][j];
}
}
dijkstra
- 不能有负权边
- 堆优化,复杂度O(nlogn)
- 代码
#include<bits/stdc++.h>
#define inf 1000000000
#define pii pair<int,int>
using namespace std;
int n,m,s,dis[100010];
bool b[100010];
int tot,h[100010],nxt[500010],to[500010],cost[500010];
void add(int x,int y,int z)
{
++tot;
nxt[tot]=h[x];
h[x]=tot;
to[tot]=y;
cost[tot]=z;
}
priority_queue<pii, vector<pii>, greater<pii> > qq;
void dij()
{
for(int i=1; i<=n; i++) dis[i]=inf;
dis[s]=0; qq.push(make_pair(0,s));
while(!qq.empty())
{
pii u=qq.top(); qq.pop();
int y=u.second;
b[y]=1;
for(int i=h[y]; i; i=nxt[i])
if(!b[to[i]] && dis[to[i]] > dis[y]+cost[i])
{
dis[to[i]]=dis[y]+cost[i];
qq.push(make_pair(dis[to[i]],to[i]));
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1; i<=m; i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
dij();
for(int i=1; i<=n; i++)
if(dis[i] == inf) printf("2147483647 ");
else printf("%d ",dis[i]);
return 0;
}
SPFA
- 复杂度O(V*E)
- 可以解决负权边
- 代码
#include<bits/stdc++.h>
#define inf 1000000000
using namespace std;
int n,m,s,dis[10010];
bool b[10010];
int tot,h[10010],nxt[500010],to[500010],cost[500010];
void add(int x, int y, int z)
{
++tot;
nxt[tot]=h[x];
h[x]=tot;
cost[tot]=z;
to[tot]=y;
}
void spfa()
{
for(int i=1; i<=n; i++) dis[i]=inf;
queue<int> qq;
qq.push(s); dis[s]=0; b[s]=1;
while(!qq.empty())
{
int u=qq.front(); b[u]=0; qq.pop();
for(int i=h[u]; i; i=nxt[i])
{
int v=to[i];
if(dis[v] > dis[u]+cost[i])
{
dis[v]=dis[u]+cost[i];
if(!b[v])
{
qq.push(v);
b[v]=1;
}
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1; i<=m; i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
spfa();
for(int i=1; i<=n; i++)
if(dis[i] != inf)cout<<dis[i]<<" ";
else cout<<2147483647<<" ";
return 0;
}
spfa和dij的区别就在于,前者每一次更改都会入队,后者只入队一次;前者是队列,后者是堆
本文详细介绍了三种经典的最短路径算法:Floyd、Dijkstra 和 SPFA。对比了它们的核心代码实现,阐述了各自的适用场景及复杂度。Floyd 算法适用于所有情况,而 Dijkstra 算法不支持负权边但可通过堆优化提高效率。SPFA 算法则能有效处理负权边问题。
1050

被折叠的 条评论
为什么被折叠?



