Bellman-Ford 求含负权最短路

该算法详解请看   https://www.cnblogs.com/tanky_woo/archive/2011/01/17/1937728.html

单源最短路   当图中存在负权边时 迪杰斯特拉就不能用了 该算法解决了此问题 时间复杂度O(nm)

注意   图中含有负圈时不成立。当判定存在负圈时,这只说明s可以到达一个负圈,并不代表s到每个点的最短路都不存在。

另外,如果图中有其他负圈但是s无法达到这个负圈,该算法也无法找到,解决方法加一个节点(还不会。。。)

该算法可以用 队列 优化 名为spfa

下面给出 有向图 的代码

 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <string.h>
 4 #include <stdlib.h>
 5 #include <iostream>
 6 #include <sstream>
 7 #include <algorithm>
 8 #include <string>
 9 #include <queue>
10 #include <ctime>
11 #include <vector>
12 using namespace std;
13 const int maxn= 1e3+5;
14 const int maxm= 1e3+5;
15 const int inf = 0x3f3f3f3f;
16 typedef long long ll;
17 int n,m,s;   //n m s 分别表示 点数-标号从1开始 边数-标号从0开始 起点
18 struct edge
19 {
20     int u,v,w;    //u为边的起点 v为边的终点 w为边的权值
21 }edges[maxm];
22 int d[maxn];   //d[i]表示 i 点到源点 s 的最短距离
23 int p[maxn];    //p[i]记录最短路到达 i 之前的节点
24 int Bellman_Ford(int x)
25 {
26     for(int i=1;i<=n;i++)
27         d[i]=inf;
28     d[x]=0;
29     for(int i=1;i<n;i++)                //  n-1次迭代
30         for(int j=0;j<m;j++)            //  检查每条边
31         {
32             if(d[edges[j].u]+edges[j].w<d[edges[j].v])    // 松弛操作
33             {
34                 d[edges[j].v]=d[edges[j].u]+edges[j].w;
35                 p[edges[j].v]=edges[j].u;           //记录路径
36             }
37         }
38     int flag=1;
39     for(int i=0;i<m;i++)                       //判断是否有负环
40         if(d[edges[i].u]+edges[i].w<d[edges[i].v])
41         {
42             flag=0;
43             break;
44         }
45     return flag;            //返回最短路是否存在
46 }
47 void Print_Path(int x)
48 {
49     while(x!=p[x])          //逆序输出 正序的话用栈处理一下就好了
50     {
51         printf("%d ",x);
52         x=p[x];
53     }
54     printf("%d\n",x);
55 }
56 int main()
57 {
58     while(scanf("%d %d %d",&n,&m,&s)!=EOF)
59     {
60         for(int i=0;i<m;i++)
61             scanf("%d %d %d",&edges[i].u,&edges[i].v,&edges[i].w);
62         p[s]=s;
63         if(Bellman_Ford(s)==1)
64             for(int i=1;i<=n;i++)
65             {
66                 printf("%d %d\n",i,d[i]);
67                 Print_Path(i);
68             }
69         else
70             printf("sorry\n");
71         return 0;
72     }
73 }

输入

6 9 1
1 2 2
1 4 -1
1 3 1
3 4 2
4 2 1
3 6 3
4 6 3
6 5 1
2 5 -1

输出
1 0
1
2 0
2 4 1
3 1
3 1
4 -1
4 1
5 -1
5 2 4 1
6 2
6 4 1

太菜了 wa~~

时间: 2024-11-05 12:11:44

Bellman-Ford 求含负权最短路的相关文章

UVa 515 - King (差分约束系统 + SPFA求带负权最短路)

下面是差分约束系统的详细介绍,以及解决方法~ 摘抄自 xuezhongfenfei(他好像也是转的....) 差分约束系统 X1 - X2 <= 0 X1 - X5 <= -1 X2 - X5 <= 1 X3 - X1 <= 5 X4 - X1 <= 4 X4 - X3 <= -1 X5 - X3 <= -3 X5 - X4 <= -3 不等式组(1) 全都是两个未知数的差小于等于某个常数(大于等于也可以,因为左右乘以-1就可以化成小于等于).这样的不等式组

spfa 算法模板 可求带负权边的最短路

它是队列优化的Bellman-Ford算法. 优化的原理是:下一次松弛操作时被更新dis的点其实与上一次被更新的点有关!如果上一次被更新的点有一条边指向某点V,那么在下一次,点V就是可能被更新dis的点. 和 Bellman-Ford 算法一样,它可以用来求带负权边的最短路,如果存在一个从源点可以到达的权重为负值的环路,则返回false表示无解决方案,因为可以不断在这个环路中循环使总代价越来越小:如果不存在则返回true. #include<iostream> #include<algo

POJ 3259 Wormholes 虫洞(负权最短路,负环)

题意:给一个混合图,求判断是否有负环的存在,若有,输出YES,否则NO.有重边. 思路:这是spfa的功能范围.一个点入队列超过n次就是有负环了.因为是混合图,所以当你跑一次spfa时发现没有负环,但是负环仍可能存在,因为有向边! 但是单源最短路也有起点啊,难道穷举起点?不用,负环是必须有某些边是带负权的,那么我们只要穷举负权边的起点就行了,因为单单跑一次spfa不能保证能遍历所有点,但是如果穷举负权边起点还没有找到负环,那么负环不可能存在(剩下的都是正权,怎么可能有负环). 1 //#incl

poj 3259 Wormholes (负权最短路,SPAF)

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 36641   Accepted: 13405 Description 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 p

SPFA 求带负权的单源最短路

int spfa_bfs(int s) { ///s表示起点: queue <int> q; memset(d,0x3f,sizeof(d)); ///d数组中存下的就是最短路径(存在的话) d[s] = 0; memset(c,0,sizeof(c));///c数组表示的是某一个节点的入队次数 memset(vis,0,sizeof(vis));///一如既往的标记数组 q.push(s); vis[s] = 1; c[s] = 1; ///顶点入队vis要做标记,另外要统计顶点的入队次数

带权最短路 Dijkstra, SPFA, Bellman-Ford, ASP, Floyd-Warshall 算法分析

转载:https://www.renfei.org/blog/weighted-shortest-path.html 图论中,用来求最短路的方法有很多,适用范围和时间复杂度也各不相同. 本文主要介绍的算法的代码主要来源如下: Dijkstra: Algorithms(<算法概论>)Sanjoy Dasgupta, Christos Papadimitriou, Umesh Vazirani;<算法竞赛入门经典-训练指南>刘汝佳.陈峰. SPFA (Shortest Path Fas

带负权图的单源最短路径算法:Bellman-Ford算法

算法简介 前面介绍过图的单源最短路径算法Dijkstra算法,然而Dijkstra算法无法判断含负权边的图的最短路.如果遇到负权,在没有负权回路存在时(负权回路的含义是,回路的权值和为负.)即便有负权的边,也可以采用Bellman-Ford算法正确求出最短路径. Bellman-Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数 w是 边集 E 的映射.对图G运行Bellman-Ford算法的结果是一个布尔值,表

poj 3259 bellman最短路判断有无负权回路

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 36717   Accepted: 13438 Description 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 p

Bellman_Ford算法求带有负边权的最短路算法

给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数. 请你求出从1号点到n号点的最多经过k条边的最短距离,如果无法从1号点走到n号点,输出impossible. 注意:图中可能 存在负权回路 . 输入格式 第一行包含三个整数n,m,k. 接下来m行,每行包含三个整数x,y,z,表示点x和点y之间存在一条有向边,边长为z. 输出格式 输出一个整数,表示从1号点到n号点的最多经过k条边的最短距离. 如果不存在满足条件的路径,则输出“impossible”. 数据范围 1≤n,k≤