图论dijkstra Bellman_Ford与Floyd算法的性质比较与实现

dijkstra,Bellman_Ford,Floyd算法的比较:
:Dijkstra算法,图所有边权值都为非负的;
:Bellman_Ford算法,图中所有边权值可以存在负值,但是不能存在原点可达的负权回路,如果存在负权回路,该算法可以给出判断;
:Floyd算法,不允许所有权值为负的回路,可以求出任意两点间的最短距离,而Dijkstra和Bellman_Ford算法只可以求出任意点到达源点的最短距离;
:Dijkstra算法的思想是贪心,Bellman_Ford和Floyd算法的思想是动态规划
:三者:图中都可以出现正权回路

Bellman_Ford算法实现

时间复杂度O(nm)

1 #define INF 10000
2 queue < int > q;
3   bool inq[ 1000 ]; // 判断是否已经在队列中
4   for ( int i = 0 ;i < n;i ++ )
5 d[i] = INF;
6 d[ 0 ] = 0 ;
7 memset(inq, false , sizeof (inq));
8 q.push( 0 );
9 inq[ 0 ] = true ;
10   while ( ! q.empty())
11 {
12 int x = q.front();q.pop();
13 inq[x] = false ;
14 for ( int i = first[x];i != NULL;i = next[i]) // 寻找所有与x相连的点
15   {
16 if (d[v[i]] > d[x] + w[i]) // 进行松弛操作
17   d[v[i]] = d[x] + w[i];
18 if ( ! inq[v[i]])
19 {
20 inq[v[i]] = true ;
21 q.push(v[i]);
22 }
23 }
24 }

Floyed算法

时间复杂度O(n^3);
动态方程:
当k=0时:d[i][j]=w[i][j]
当k>=1时:d[i][j]=min(d[i][j],d[i][k]+d[k][j])

1 for ( int k = 0 ;k < n;k ++ )
2 for ( int i = 0 ;i < n;i ++ )
3 for ( int j = 0 ;j < n;j ++ )
4 if (d[i][k] + d[k][j] < d[i][j])
5 d[i][j] = d[i][k] + d[k][j]

Dijkstra算法伪代码及代码

从单个原点出发到所有节点的最短路径。该算法适用于有向图和无向图
初始化G,s
S=空
Q=V[G];
d=无穷
while(!Q.isempty())
{
在d中选出最小值对应的下标为u
 S=S+u
 Q=Q-u
 对于所有从u出发的边(u,y)更新d[y]=min{d[y],d[u]+map[u,y]};
 }
 利用father数组记录路径
 时间复杂度O(n*n)
 优化dijkstra算法为:dijkstra+优先队列 时间复杂度O(MlogN);

1 #include < iostream >
2 #include < queue >
3 using namespace std;
4 int G[ 12 ][ 12 ],E[ 12 ][ 12 ],d[ 12 ],mark[ 12 ],N,x,y,z;
5 /*
6 x为起点y为终点 z为距离
7 G存储图,E存储边,d存储距离,mark判断该点是否已经算过
8 */
9 struct node
10 {
11 int valu;
12 int index;
13 friend bool operator < (node a,node b)
14 {
15 return a.valu > b.valu;
16 }
17 }t,st; // 重载运算符<
18 int main()
19 {
20 while (cin >> N)
21 {
22 for ( int i = 0 ;i < 12 ;i ++ )
23 G[i][ 0 ] = 0 ,d[i] = 1000 ,mark[i] = 0 ; // 初始化
24 d[ 1 ] = 0 ;
25 while (N -- )
26 {
27 cin >> x >> y >> z;
28 G[x][ ++ G[x][ 0 ]] = y;
29 E[x][ ++ E[x][ 0 ]] = z;
30 }
31 priority_queue < node > q; // 声明优先队列
32 t.valu = 0 ,t.index = 1 ;
33 q.push(t);
34 while ( ! q.empty())
35 {
36 t = q.top();
37 q.pop();
38 if (mark[t.index]) // 如果已经算过则跳过
39 continue ;
40 mark[t.index] = 1 ;
41 for ( int i = 1 ;i <= G[t.index][ 0 ];i ++ )
42 {
43 if (d[t.index] + E[t.index][i] < d[G[t.index][i]]) // 松弛操作
44 {
45 d[G[t.index][i]] = d[t.index] + E[t.index][i];
46 st.valu = d[G[t.index][i]];
47 st.index = G[t.index][i];
48 q.push(st);
49 }
50 }
51 }
52 cout << " 原点为1每一点到原点的最短距离为: " << endl;
53 for ( int i = 1 ;i < 6 ;i ++ )
54 cout << d[i] << " " ;
55 cout << endl;
56 }
57 }
58 /*
59 9
60 1 2 10
61 1 3 3
62 2 3 1
63 3 2 4
64 2 4 2
65 3 4 8
66 3 5 2
67 4 5 7
68 5 4 9
69 */

转载于:https://www.cnblogs.com/penseur/archive/2011/03/01/1967944.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值