floyd | dijkstra | Bellman-ford | |
---|---|---|---|
空间复杂度 | o(N^2) | 0(M) | 0(M) |
时间吗复杂度 | O(N3) | O((M+N)logN) | O(MN) |
适用情况 | 稠密图 | 稠密图 | 稀疏图 |
负权边 | 不可以 | 不可以 | 可以 |
floyd算法简单,dijkstra不能解决负权边优化后可以得到MLogN的复杂度,bellman可以解决负权边。
下面再介绍一下贝尔曼、福特算法的优化
给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了。 我们约定有向加权图G不存在负权回路,即最短路径一定存在。当然,我们可以在执行该算法前做一次拓扑排序,以判断是否存在负权回路,但这不是我们讨论的重点。
算法思想:我们用数组d记录每个结点的最短路径估计值,用邻接表来存储图G。我们采取的方法是动态逼近法:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止
期望的时间复杂度O(k e), 其中k为所有顶点进队的平均次数,可以证明k一般小于等于2。
实现方法:
建立一个队列,初始时队列里只有起始点,再建立一个表格记录起始点到所有点的最短路径(该表格的初始值要赋为极大值,该点到他本身的路径赋为0)。然后执行松弛操作,用队列里有的点作为起始点去刷新到所有点的最短路,如果刷新成功且被刷新点不在队列中则把该点加入到队列最后。重复执行直到队列为空。
判断有无负环:
如果某个点进入队列的次数超过N次则存在负环(SPFA无法处理带负环的图)
暂时先给出代码,具体我也没理解清楚;
#include<stdio.h>
#include<string.h>
#include<queue>
#define N 210
#define M 2010
#define INF 0x3f3f3f3f//定义无穷大
using namespace std;
int dis[N],vis[N],head[N],n,m,edgenum;
struct node{
int from,to,cost,next;
}edge[M];
void init(){
edgenum=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w){
node E={u,v,w,head[u]};
edge[edgenum]=E;
head[u]=edgenum++;
}
void spfa(int beg,int end){//SPFA算法核心
queue<int>q;
q.push(beg);//将起点加入队列
memset(vis,0,sizeof(vis));//用来标记是否在队列中
memset(dis,INF,sizeof(dis));
vis[beg]=1;
dis[beg]=0;
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=0;
int i;
for(i=head[u];i!=-1;i=edge[i].next){//遍历起点为U的所有的边。
int v=edge[i].to;
if(dis[v]>dis[u]+edge[i].cost){//更新点的最短路
dis[v]=dis[u]+edge[i].cost;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
if(dis[end]==INF)
printf("-1\n");
else
printf("%d\n",dis[end]);
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF&&n!=0&&m!=0){
init();//需要初始化邻接表的表头。
while(m--){
int a,b,cost;
scanf("%d%d%d",&a,&b,&cost);
add(a,b,cost);//对图进行输入,由于是无向图,所以正反两次输入,不用判断重边。
add(b,a,cost);
}
int beg,end;
scanf("%d%d",&beg,&end);
spfa(beg,end);
}
return 0;
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114870.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...