最短路问题 - dijkstra算法、Bellman_Ford算法、SPFA模板、Floyd算法

寻找最短路径指的是找出从图中某个结点出发到达另一个结点所经过的边的权重之和最小的那条路径。这里的最短路不仅仅指一般意义上的距离最短,还可以引申到时间,费用等最小。

算法中的最短路问题类型:
1:单源最短路:给定一个源结点,求出这个点到其他所有点的最短路径,有Dijkstra和Bellman-ford两种算法,Dijkstra只能求解所有边权都为正的情况,Bellman-ford可以求解边权为正或为负但没有负环的情况。
2:多源最短路:求出图中每个结点到其他所有结点的最短路,可用Floyd算法解,Floyd同样可求解有负边无负环的情况。

3:点对点最短路:给定起点和终点,求这两点间的最短路径。通常用BFS(广搜)和DFS(深搜)求解。

dijkstra算法

需要设的变量:

1:cost数组,cost[i][j]代表从i到j的距离(或费用等任意权值)。

2:d数组,d[i]代表源点到结点i的最短路,初始值为无限大。

3:used数组,used[i]表示结点i是否被使用,初始为0,表示没被使用

算法步骤

初始化cost数组为INF,然后读入边的值

初始化d数组为INF,设d[s]=0,s为原点

初始化used数组为0,表示都没用过

1:将源点s的d值设置为0,used[s]=1,遍历与s有边相连的所有结点i,并将他们的d值设置为u,i之间的距离cost[u][i]。
2:在used[i]=0的结点中找一个到源点的距离最小的点v,并把它的used值设为1。
3:遍历与v有边相连的所有结点i,如果源点到i的距离d[i]大于从源点到v的距离d[v]与i,v之间的距离cost[i][v]的加和,那么将d[i]设置为d[v]+cost[i][v](这个步骤称为边的松弛,等于从源点到i时多走了一步,变成先到v再到i,松弛操作即松弛点,经过的点数变多,缩小距离)。
4:重复步骤2+3  n-1次,直到最后一个结点被加入,结束。

图解:

例题:

 

在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? 
 

Input输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。 
输入保证至少存在1条商店到赛场的路线。 
Output对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间Sample Input

2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0

Sample Output

3
2

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=105,INF=0x3f3f3f3f;
int d[N],w[N][N],vis[N],n,m;

void Dijkstra(int s){
    for(int i=0;i<=n;i++){//每个点到原点的最短距离
        d[i]=INF;
    }
    d[s]=0;
    memset(vis,0,sizeof(vis));

    for(int i=1;i<=n;i++){
        int v=-1;
        for(int j=1;j<=n;j++){//对于每一个点,找到最近的一个点
            if(!vis[j]&&(v==-1||d[j]<d[v]))v=j;
        }

        vis[v]=1;
        for(int k=1;k<=n;k++){
            d[k]=min(d[k],d[v]+w[v][k]);
        }
    }
}

int main(){
    int a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0&&m==0)break;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                w[i][j]=INF;
            }
        }
        while(m--){
            scanf("%d%d%d",&a,&b,&c);
            w[a][b]=w[b][a]=c;
        }

        Dijkstra(1);
        printf("%d\n",d[n]);
    }
}

dijkstra算法的优化:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef pair<int,int> P;
const int N=105,INF=0x3f3f3f3f;
int d[N],n,m;

struct edge{
    int to,cost;
};

vector<edge>G[N];

void Dijkstra(int s){
    for(int i=1;i<=n;i++){//每个点到原点的最短距离
        d[i]=INF;
    }
    d[s]=0;
    priority_queue<P,vector<P>,greater<P> >q;

    q.push(P(d[s],s));//按边的权值排序

    while(!q.empty()){
       P p=q.top();q.pop();

       int v=p.second;//顶点的编号

       if(d[v]<p.first)continue;

       for(int i=0;i<G[v].size();i++){
           edge e=G[v][i];//点v到i的情况(点i的值和v到i的路径)
           if(d[e.to]>d[v]+e.cost){
               d[e.to]=d[v]+e.cost;
               q.push(P(d[e.to],e.to));
           }
       }
    }
}
int main(){
    int a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0&&m==0)break;
        memset(G,0,sizeof(G));
        while(m--){
            scanf("%d%d%d",&a,&b,&c);
            G[a].push_back({b,c});
            G[b].push_back({a,c});
        }

        Dijkstra(1);
        printf("%d\n",d[n]);
    }
}

 

贝尔曼-福特算法和狄克斯特拉算法类似,只不过每次随机寻找边进行更新。

 

检查是否存在负:如果在进行过n-1次松弛操作后还存在可以松弛的边,那么说明有负环。

(如果没有负环的话松弛操作完后,d[i]就表示点i到原点最小的长度,还能再松弛说明有一个边是负的)

时间复杂度:O(VE),用队列优化复杂度为O(kE),k为每个节点入队次数,也就是SPFA算法。

例题:

 

While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..NM (1 ≤ M≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.

As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .

To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.

Input

Line 1: A single integer, FF farm descriptions follow. 
Line 1 of each farm: Three space-separated integers respectively: NM, and W 
Lines 2.. M+1 of each farm: Three space-separated numbers ( SET) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path. 
Lines M+2.. MW+1 of each farm: Three space-separated numbers ( SET) that describe, respectively: A one way path from S to E that also moves the traveler backT seconds.

Output

Lines 1.. F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).

Sample Input

2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8

Sample Output

NO
YES

Hint

For farm 1, FJ cannot travel back in time. 
For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.

Bellman_Ford

 

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
 
#define INF 0x3f3f3f3f
 
using namespace std;
struct proc{int from,to,cost;};
proc edge[6000];
int d[505],n,m,w,cnt;
 
void addEdge(int s,int e,int c){
    edge[cnt].from=s;
    edge[cnt].to=e;
    edge[cnt++].cost=c;
}
int Bellman(){
    int flag;
    memset(d,INF,sizeof(d));
    d[1]=0;
    for(int i=1;i<=n;i++){
        flag=0;
        for(int j=1;j<=cnt;j++){//存的边的数量
            if(d[edge[j].to]>d[edge[j].from]+edge[j].cost){
                d[edge[j].to]=d[edge[j].from]+edge[j].cost;
                flag=1;
             }
        }
        if(!flag)break;
    }
    //寻找负环
    
    for(int i=1;i<=cnt;i++){
        if(d[edge[i].to]>d[edge[i].from]+edge[i].cost)return 1;
    }
    return 0;
}
int main(){
    int f,s,e,c;
    scanf("%d",&f);
    while(f--){
        cnt=1;
        scanf("%d%d%d",&n,&m,&w);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&s,&e,&c);
            addEdge(s,e,c);
            addEdge(e,s,c);
        }
        for(int i=1;i<=w;i++){
            scanf("%d%d%d",&s,&e,&c);
            addEdge(s,e,-c);
        }
        if(Bellman())printf("YES\n");
        else printf("NO\n");
    }
}

SPFA算法:

(注意:init要在输入n后再调用,这样d数组才会被正确地更新)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int>P;
const int INF=0x3f3f3f3f;
const int N=510;
int n,m,w,cnt;
struct A{
    int to,nex,cost;
}edge[6000];

int head[N],d[N],vis[N],tot[N];

void add(int from,int to,int cost){
	edge[cnt].to=to;
	edge[cnt].cost=cost;
	edge[cnt].nex=head[from];
	head[from]=cnt++;
}


void init(){
	memset(vis,0,sizeof(vis));
	memset(head,-1,sizeof(head));
	for(int i=1;i<=n;i++){
        d[i]=INF;
	}
	memset(tot,0,sizeof(tot));
	cnt=0;
}

int spfa(){
	queue<int>q;
	q.push(1);
	d[1]=0;
	vis[1]=1;
	tot[1]=1;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int p=head[u];p!=-1;p=edge[p].nex){
			int v=edge[p].to;
			if(d[v]>d[u]+edge[p].cost){
				d[v]=d[u]+edge[p].cost;
				if(!vis[v]){
					vis[v]=1;
					tot[v]++;
					if(tot[v]>n)return 1;
					q.push(v);
				}
			}
		}
	}
	return 0;
}

int main(){
	int T,s,e,c;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d%d",&n,&m,&w);
		init();
		for(int i=1;i<=m;i++){
			scanf("%d%d%d",&s,&e,&c);
		    add(s,e,c);
		    add(e,s,c);
		}
		for(int i=1;i<=w;i++){
			scanf("%d%d%d",&s,&e,&c);
			add(s,e,-c);
		}
		if(spfa())printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

Floyd算法:

求解任意两点的最短路问题,设数组d[i][j]表示点i到j的最短路径,初始值:d[i][j]=INF(没有路径,i!=j),d[i][i]=0;

核心代码:

void floyd(){
    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]);
            }
        }
    }
}

例题:Floyd算法解决传递闭包问题

Cow Contest

N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we all know, some cows code better than others. Each cow has a certain constant skill rating that is unique among the competitors.

The contest is conducted in several head-to-head rounds, each between two cows. If cow A has a greater skill level than cow B (1 ≤ A ≤ N; 1 ≤ B ≤ NA ≠ B), then cow A will always beat cow B.

Farmer John is trying to rank the cows by skill level. Given a list the results of M(1 ≤ M ≤ 4,500) two-cow rounds, determine the number of cows whose ranks can be precisely determined from the results. It is guaranteed that the results of the rounds will not be contradictory.

Input

* Line 1: Two space-separated integers: N and M
* Lines 2..M+1: Each line contains two space-separated integers that describe the competitors and results (the first integer, A, is the winner) of a single round of competition: A and B

Output

* Line 1: A single integer representing the number of cows whose ranks can be determined
 

Sample Input

5 5
4 3
4 2
3 2
1 2
2 5

Sample Output

2

题意:n个人m个回合,在m行中,给出a,b表示a能打败b,问经过m个回合,n个人中,几个人的等级可以确定

传递闭包即是:已知i能到j,j能到k,则i能到k

若1个人与其他n-1个人的关系可以确定,那么他的等级就可以确定。

要注意的是这里的d数组初始化为0,表示还不知道i,j的关系,有关系则为1,这里设为INF就不行啦吧啊哈哈。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
int n,m;
int d[103][103];

void floyd(){
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                d[i][j]=d[i][j]||(d[i][k]&&d[k][j]);
            }
        }
    }
}

int main(){
    int a,b;
    scanf("%d%d",&n,&m);
    memset(d,0,sizeof(d));
    while(m--){
        scanf("%d%d",&a,&b);
        d[a][b]=1;
    }
    floyd();
    int ans=0;
    for(int i=1;i<=n;i++){
        int sum=0;
        for(int j=1;j<=n;j++){
            if(d[i][j]||d[j][i])sum++;
        }

        if(sum==n-1)ans++;
    }
    printf("%d\n",ans);
}

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本科参加ACM竞赛的过程中积累下来的一部分算法模板,和自己在PKU上面做的一部分题目。 模板目录结构: 目录: 动态规划 O(n^2)的最长上升子序列 nlogn最长上升子序列 高精度 计算几何 Graham扫描法 两线段交点 凸多边形面积 半平面交 计算几何库 数据结构 闭散列法整数hash 开散列法整数hash 字符串hash 堆 二维树状数组 Trie树 二叉查找树 线段树 RMQ LCA+RMQ SB-Tree 数论 生成紧凑素数表 分解质因子 最大公约数 a^b mod n 扩张欧几里德算法 素数表质因子分解 Stirling公式 中国剩余定理 欧拉数(递推法) 欧拉数(公式法) 十进制转负进制 归并排序求逆序数 Pell方程 Catalan数,100以内 欧拉函数讲解 组合计数 组合数计算(double) 组合数计算(高精度) r-组合生成算法 r-排列生成算法 r-错位排列生成算法 图论 传递闭包 欧拉回路判定 有向图欧拉路径 二分图最大匹配 匈牙利算法 二分图最大匹配 HK算法 二分图最大权匹配 KM算法 割边 强连通分量 缩点 Kosaraju算法 最大团 最小树形图 无向图全局最小割 stoer-wagner O(n^3) 最短路径优先算法 SPFA 网络流 最大流:Ford&Fulkerson算法 最大流:Dinic算法 最大流:ek算法 最大流:dsp算法 最大流:hlpp算法 最小费用最大流:bellman_ford找增广路 最小费用最大流:ssp算法 字符串 KMP 通配符匹配 最小表示法 后缀数组 倍增算法 基于多串匹配的有限状态自动机 未分类 归并排序 星期几的计算 N皇后构造法 几个常用的位操作 最大最小定理总结 0/1分数规划总结 (by yxysdcl 2008/11/19) 代码目录结构: 目录: 动态规划 钉子和小球 Hash+dp分词(摩尔电码) 火柴棒等式 DAG图DP,老鼠打洞 最短子路径 最少回文数 矩阵链乘 树形DP 最少的石子填到根节点 树种删除最少的边使刚好剩下P个点 树的支配集 最优连通子集 带背包的树形DP 最小顶点覆盖,判唯一 用最少的点覆盖所有的边 DAG上的记忆化树形DP,博弈 有限状态自动机+树形DP 状态压缩DP 炮兵阵地 Help Bob,买匹萨 匹配数量 堆筛子 全排列式状态DP 计算几何 多边形地图染色 数据结构 Hash 枚举+hash,方程解数 点集对称中心 字符hash,统计出现最多的单词 类此The Happy worm 数据结构 树状数组 覆盖某区间数量统计 Cows Stars 两个树桩数组 二维树状数组 数据结构 双端队列 Sliding Window 数据结构 线段树 Cows 线段染色 排队问题 第K大的数 离散化+线段树 灯光投影 网络赛取连续子序列问题 线段树+树状数组+并查集,转化为排队问题 离散化 离散化矩形切割,矩形覆盖面积统计 覆盖矩形周长统计 离散化矩形切割 灯光投影 搜索 导弹 Bfs+hash状态的抽象,模关系 Bfs变形,钥匙与门 双向广搜 迭代加深 优先队列搜索,过最少的门救人,建图 A*搜索 图论 差分约束 Intervals bellman_ford Intervals SPFA 出纳员的雇佣 不等式组 图论 割边 图染色 拓扑 树 欧拉路径) 割点+统计删除后剩下多少连通图 删除一个点使得连通分量最多 图染色 拓扑排序全部序列 最大生成树 有向图欧拉路径 字典序最小的有向图欧拉路径 图论 匹配 完美匹配FBI Koning定理,泥地 二分图最大独立集 通讯站天线覆盖 二分图拆分后匹配 二分图某边唯一匹配 最小权匹配 海上矿工 floyd预处理 最大权匹配,需要非完全图转完全图 传递闭包+最小路径覆盖 可以重复经过点 图论 网络流 Adding-the-maximum-flow arc 增量网络流 区间枚举,猴子语言+网络流 最小费用最大流 最大流最小割定理 摧毁伞兵 最大流最小割定理 泥地 图论 最短路Dijkstra+heap 昂贵的聘礼 最短路变形 树中任意点对最短路Bellman_ford 货率 限制长度最短路,负环判连通,点权变边权,改变正负号 表达式求值 算法优先算法求表达式的值 词法分析与算法优先算法,集合运算:差集,并集,交集 矩阵乘法 线段覆盖数量 矩阵构造,nlogn矩阵乘法 2-SAT XOR
Algorithms &emsp;&emsp;本次README修订为算法仓库Algorithms的第100次commit,首先我们庆祝自2016年8月4日本仓库建立以来Dev-XYS在算法学习方面取得的显著进步! &emsp;&emsp;这里有各种算法的C++代码,任何人可以在自己的任何程序中使用,欢迎大家指出代码中的错误以及有待改进的地方。 &emsp;&emsp;本仓库内所有代码的授权方式为Unlicense,大家如果使用我的代码开发自己的软件挣了大钱,或是参考我的代码在NOI中得了金牌,我都会很高兴的。使用这里的代码之后,你可以自主选择是否公开源代码。总而言之,你可以把这里的代码当作你自己写的一样,无论怎样使用都是被允许的。但是,我不对本仓库内代码的正确性负责。大家要是使用我的代码开发软件而导致程序崩溃,或是参考我的代码在考试时出错,请不要向我抱怨。如果你愿意,遇到问题可以在Issues中提出来,我们共同解决。我们不赞成Pull Request,因为本仓库主要储存作者已经学习的算法,全部代码均由作者本人负责维护与更新。 &emsp;&emsp;以下索引提供了本仓库内算法的中文名,方便大家查找。更新可能有很长时间的延迟,不保证所有算法的名称都在列表中出现。 Index --------------------------Contents-------------------------- --------------------------FileName-------------------------- AC自动机 Aho-Corasick-Automation 单源最短路径(SPFABellman-Ford(Queue-Optimised) 单源最短路径(Bellman-Ford) Bellman-Ford 使用Edmonds-Karp进行二分图匹配 Bigrpah-Matching(Edmonds-Karp) 普通的二叉搜索树 Binary-Search-Tree 广度优先搜索 Breadth-First-Search 冒泡排序 Bubble-Sort 桶排序 Bucket-Sort 组合数的递推求解 Combination(Recursion) 枚举组合 Combination 基本的复数类 Complex-Number 割点 Cut-Vertex 深度优先搜索 Depth-First-Search 堆优化的Dijkstra算法 Dijkstra(Heap-Optimised) 并查集 Disjoint-Set-Union 最大流Edmonds-Karp算法 Edmonds-Karp 欧拉函数 Euler's-Totient-Function 有向图的欧拉回路 Eulerian-Tour(Digraph) 拓展欧几里得算法 Extended-Euclid 简单的快速幂 Fast-Exponentiation 树状数组 Fenwick-Tree 所有结点对之间的最短路径(FloydFloyd-Warshall 凸包算法(Graham扫描法) Graham-Scan 辗转相除法求最大公约数 Greatest-Common-Divisor 堆排序 Heap-Sort ISAP算法 Improved-Shortest-Augmenting-Path(Naive) 插入排序 Insertion-Sort 字符串匹配(KMP) Knuth-Morris-Pratt 最小生成树(Kruskal) Kruskal 最近公共祖先(Tarjan) Least-Common-Ancestor(Tarjan) 使用后缀数组求解最长公共子串 Longest-Common-Substring 最长上升子序列(n·log(n)) Longest-Increasing-Subsequence(n·log(n)) 倍增法求最近公共祖先 Lowest-Common-Ancestor(Doubling) 朴素的矩阵乘法 Matrix-Multiplication(Naive) 归并排序 Merge-Sort 最小堆 Min-Heap 乘法逆元 Modular-Multiplicative-Inverse 仅支持单点修改的可持久化线段树(维护区间和值) Persistent-Segment-Tree(Sum) 试除法素数测试 Prime-Check(Naive) 线性的素数筛法 Prime-Sieve(Linear) 队列的基本操作 Queue 快速排序的优化版本 Quick-Sort(Extra-Optimised) 快速排序的随机化版本 Quick-Sort(Randomized) 快速排序 Quick-Sort 使用向量叉积判断两个有向线段的时针关系 Segment-Direction 线段树维护区间最大值 Segment-Tree(Maximum) 线段树维护区间最小值 Segment-Tree(Minimum) 线段树维护区间和值 Segment-Tree(Sum) 普通的选择算法 Selection Eratosthenes素数筛法 Sieve-of-Erotosthenes 指针版的单向链表 Singly-Linked-List(Pointer) 跳表 Skip-List ST表 Sparse-Table 伸展树 Splay 博弈论SG函数 Sprague-Grundy 栈的基本操作 Stack 递推法求解无符号第一类斯特林数 Stirling-Number(Cycle,Unsigned,Recursion) 递推法求解第二类斯特林数 Stirling-Number(Subset,Recursion) 倍增法求解后缀数组 Suffix-Array(Doubling) 倍增法求解后缀数组(附带Height数组) Suffix-Array-with-Height(Doubling) 使用Tarjan算法求解强连通分量 Tarjan(Strongly-Connected-Components) 数组版的字典树 Trie(Array) 指针版的字典树 Trie(Pointer)
Dijkstra算法Bellman-Ford算法都是用于解决图中单源最短路径问题的经典算法Dijkstra算法是一种贪心算法,用于求解从给定源节点到其他所有节点的最短路径。算法通过维护一个优先队列(或最小堆)来选择当前距离源节点最近的节点,并逐步扩展路径长度最短的节点。具体步骤包括:初始化源节点的距离为0,将其加入优先队列;从队列中取出距离最小的节点,并对其相邻节点进行松弛操作,更新其距离;重复上述步骤直到队列为空。 Bellman-Ford算法是一种动态规划算法,可以处理带有负权边的图。算法通过对所有边进行V-1轮松弛操作来逐步求解最短路径。具体步骤包括:初始化源节点距离为0,其他节点距离为正无穷;迭代V-1轮,对所有边进行松弛操作,即尝试通过更新边权值来缩短源节点到其他节点的距离;检测是否存在负权回路,如果存在则说明图中存在无限负权路径。 两者的主要区别在于: - Dijkstra算法要求图中边权值非负,而Bellman-Ford算法可以处理带负权边的情况。 - Dijkstra算法的时间复杂度为O((V + E)logV),其中V为节点数量,E为边数量;而Bellman-Ford算法的时间复杂度为O(VE),在稀疏图中效率较低。 选择使用哪种算法取决于具体的问题场景和图的特性。如果图中不存在负权边,且需要求解单源最短路径,Dijkstra算法是一个较好的选择。而如果图中可能存在负权边,并且需要检测负权回路,或者只需求解单源最短路径且图较稠密,可以考虑使用Bellman-Ford算法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值