Bellman_Ford和Spfa两种方法判断负环

Dijkstra、Bellman_Ford、SPFA、Floyd算法复杂度比较 Dijkstra:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度O(E+VlgV) BellmanFord:适用于权值有负值的图的单源最短路径,并且能够检测负圈,复杂度O(VE) SPFA:适用于权值有负值,且没有负圈的图的单源最短路径,论文中的复杂度O(kE),k为每个节点进入Queue的次数,且k一般但此处的复杂度证明是有问题的,其实SPFA的最坏情况应该是O(VE). Flo 阅读详情

  Bellman_Ford是通过N-1次循环求出每个点到原点的最短路的,每次循环遍历所有的边,如果能更新就更新。前面说过为什么N-1次就行(若一个点到起点的最短路需要经过N个点,包括他自己,那么第N次循环就能确定他的最短路)。

  最短路一定是不含环的,如果存在负环就根本不存在最短路了。所以这个方法可以用来判断是否有负环,如果循环了N-1次后还能进行松弛操作,说明有负环。Bellman_Ford的复杂度是O(M*N)。

 

int bellman(){   //G条边
    int i,j,k;
    memset(d,INF,sizeof(d));
    d[0]=0;
    for(i=0;i<N-1;i++){
        for(j=0;j<G;j++){
            int u=e[j].u,v=e[j].v;
                if(d[u]!=INF&&d[u]+w[u][v]<d[v]) d[v]=d[u]+w[u][v];
        }
    }
    for(j=0;j<G;j++){
        int u=e[j].u,v=e[j].v;
            if(d[u]!=INF&&d[u]+w[u][v]<d[v]) return 1;
    }
    return 0;
}

  因为再次循环的时候有些点的d根本没有被更新,再用这个点去更新别的点的话就浪费时间了。对Bellman_Ford改进,Spfa算法是用一个队列,每次取出一个点,更新和他连接的点,如果被更新的点不在队列中就加入队列中,这样就避免了那个问题。因为是对每个点连接的点操作,这就需要链接表了(可以用vector数组)。还需要一个数组inq判断当前这个点是否在队列里。

  如果用spfa判断是否有负环问题,其实原理也是一个点不能被更新N-1次以上,所以再开一个数组记录每个点被加入队列的次数。在网上看说是一个点被加入N次以上就说明有负环,想了半天为什么是N次以上。。。后来发现因为这是有特殊情况的,N=1,这个点被加入一次,但是没负环。。。所以只要判断这个特殊情况,后面条件写成N-1次以上也是对的。。当然为了方便,直接写成N次以上更好。。网上说这个期望时间复杂度O(2*e),这个我就不知道怎么算的了。。。

int spfa(){
    queue<int> q;
    memset(d,INF,sizeof(d));
    memset(inq,0,sizeof(inq));
    memset(cnt,0,sizeof(cnt));
    d[0]=0;
    inq[0]=1;
    q.push(0);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        inq[x]=0;
        cnt[x]++;
        if(cnt[x]>N) return 1;
        if(d[x]==INF) continue;
        for(int i=0;i<v[x].size();i++){
            int y=v[x][i].y;
            if(d[x]+v[x][i].t<d[y]){
                d[y]=d[x]+v[x][i].t;
                inq[y]=1;
                q.push(y);
            }
        }
    }
    return 0;
}

  Wormholes 

In the year 2163, wormholes were discovered. A wormhole is a subspace tunnel through space and time connecting two star systems. Wormholes have a few peculiar properties:

  • Wormholes are one-way only.
  • The time it takes to travel through a wormhole is negligible.
  • A wormhole has two end points, each situated in a star system.
  • A star system may have more than one wormhole end point within its boundaries.
  • For some unknown reason, starting from our solar system, it is always possible to end up in any star system by following a sequence of wormholes (maybe Earth is the centre of the universe).
  • Between any pair of star systems, there is at most one wormhole in either direction.
  • There are no wormholes with both end points in the same star system.

All wormholes have a constant time difference between their end points. For example, a specific wormhole may cause the person travelling through it to end up 15 years in the future. Another wormhole may cause the person to end up 42 years in the past.


A brilliant physicist, living on earth, wants to use wormholes to study the Big Bang. Since warp drive has not been invented yet, it is not possible for her to travel from one star system to another one directly. Thiscan be done using wormholes, of course.


The scientist wants to reach a cycle of wormholes somewhere in the universe that causes her to end up in the past. By travelling along this cycle a lot of times, the scientist is able to go back as far in time as necessary to reach the beginning of the universe and see the Big Bang with her own eyes. Write a program to find out whether such a cycle exists.

Input 

The input file starts with a line containing the number of cases c to be analysed. Each case starts with a line with two numbersn andm . These indicate the number of star systems ($1 \le n \le 1000$) and the number of wormholes ($0 \le m \le 2000$) . The star systems are numbered from 0 (our solar system) throughn-1 . For each wormhole a line containing three integer numbersx,y andt is given. These numbers indicate that this wormhole allows someone to travel from the star system numberedx to the star system numberedy, thereby ending upt ($-1000 \le t \le 1000$) years in the future.

Output 

The output consists of c lines, one line for each case, containing the wordpossible if it is indeed possible to go back in time indefinitely, ornot possible if this is not possible with the given set of star systems and wormholes.

Sample Input 

2
3 3
0 1 1000
1 2 15
2 1 -42
4 4
0 1 10
1 2 20
2 3 30
3 0 -60

Sample Output 

possible
not possible

#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#define INF 0x3f3f3f3f
#define MAXN 1010
#define pii pair<int,int>
using namespace std;
int N,M,G,w[MAXN][MAXN],d[MAXN],inq[MAXN],cnt[MAXN];
struct edge{
    int y,t;
    edge(int a,int b){
        y=a;
        t=b;
    }
};
vector<edge> v[MAXN];

struct Bellman_edge{
    int u,v,t;
    Bellman_edge(){}
    Bellman_edge(int a,int b,int d){
        u=a;
        v=b;
        t=d;
    }
}e[2*MAXN];

int bellman(){   //G条边
    int i,j,k;
    memset(d,INF,sizeof(d));
    d[0]=0;
    for(i=0;i<N-1;i++){
        for(j=0;j<G;j++){
            int u=e[j].u,v=e[j].v;
                if(d[u]!=INF&&d[u]+w[u][v]<d[v]) d[v]=d[u]+w[u][v];
        }
    }
    for(j=0;j<G;j++){
        int u=e[j].u,v=e[j].v;
            if(d[u]!=INF&&d[u]+w[u][v]<d[v]) return 1;
    }
    return 0;
}
int spfa(){
    queue<int> q;
    memset(d,INF,sizeof(d));
    memset(inq,0,sizeof(inq));
    memset(cnt,0,sizeof(cnt));
    d[0]=0;
    inq[0]=1;
    q.push(0);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        inq[x]=0;
        cnt[x]++;
        if(cnt[x]>N) return 1;
        if(d[x]==INF) continue;
        for(int i=0;i<v[x].size();i++){
            int y=v[x][i].y;
            if(d[x]+v[x][i].t<d[y]){
                d[y]=d[x]+v[x][i].t;
                inq[y]=1;
                q.push(y);
            }
        }
    }
    return 0;
}
int main(){
    freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&N,&M);
        memset(w,INF,sizeof(w));
        int i,a,b,t;
        G=0;
        for(i=0;i<N;i++) v[i].clear();
        for(i=0;i<N;i++) w[i][i]=0;
        for(i=0;i<M;i++){
            scanf("%d%d%d",&a,&b,&t);
            w[a][b]=t;                      //bellman
            e[G++]=Bellman_edge(a,b,t);
            v[a].push_back(edge(b,t));      //spfa
        }
        if(bellman()) printf("possible\n");
        else printf("not possible\n");
    }
    return 0;
}



P3385 【模板】负环 spfa判断负环 P3385 【模板】负环 题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 寻找一个从顶点1所能到达的负环,负环定义为:一个边权之和为负的环。 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个顶点,M条边 接下来M行,每行三个整数a b w,表示a->b有一条权值为w的边(若w&l... 阅读详情

相关推荐

ksz9031 mmd读取不了_ZYNQ. LwIP.PHY.KSZ9031RNX

新一块板子米尔科技的z-turn 使用的PHY芯片是Micrel的 KSZ9031RNX 而不是zedboard上的Marvell的。直接使用lwip的echo server demo时会报错 , 无法启动。在网上找了很久终于找到几篇关于这个问题的文章。修改PHY的驱动xemacpsif_physpeed.c文件该芯片的PHY Identifier 是 0x0022bsp设置中修改参数以提速MEM...

weixin_39626298的博客 924

Bellman-Ford-贝尔曼-福特-算法求最短路-负环

Bellman-Ford-贝尔曼-福特-算法求最短路-负环

重生之我是cxk的博客 815

基于 AUTOSAR 的域控产品软件开发进阶探索

本文深入探讨了AUTOSAR架构在汽车域控产品开发中的进阶应用。首先从系统设计角度分析了AUTOSAR分层架构原理及其在域控产品中的优化部署策略;其次详细介绍了Davinci和EBTresos等主流工具链的特点与协同使用方法;然后重点阐述了ASPICE流程与功能安全/信息安全标准的实施要点;最后分享了多核车载芯片(如NXP S32G)的适配经验与优化实践。通过架构设计、工具运用、标准遵循和芯片适配四个维度的专业解析,为域控产品的AUTOSAR开发提供了系统性指导。

SiArch的博客 1199

bellman-ford算法(判断是否存在负环)

Bellman-ford算法的一个重要应用是判负环。在迭代n-1次后如果还可以进行松弛操作,说明一定存在负环。如果采用队列实现,那么当某个结点入队了n次时可以判断出存在负环,代码如下: #include #include #include #include #include #include using namespace std; const int maxn = 1001; struct E

蒻菜_羊羊羊的专栏 4795

从零到一:RV1126与IMX415的硬件交响曲——深入解析Linux IPC摄像头的硬件调试艺术

本文深入解析了RV1126与IMX415组合的Linux IPC摄像头硬件调试技术,涵盖硬件接口检查、设备树配置、驱动加载验证及ISP调优等关键步骤。通过详细的操作指南和常见问题解决方案,帮助开发者快速掌握摄像头调试技巧,提升开发效率。

weixin_29161785的博客 978

工业视觉开发者的福音:用C#玩转VisionMaster算子(非方案版完整教程)

本文为工业视觉开发者提供了一份完整的C#与VisionMaster算子二次开发教程,详细介绍了环境配置、算子调用原理、性能优化技巧及实战案例。通过模板匹配和二维码识别等实例,展示了如何高效集成VisionMaster算子到现有框架中,提升工业自动化视觉检测系统的灵活性和性能。

weixin_29280657的博客 270

检查是否有负循环(Bellman Ford, Floyd-Warshall)

 负循环:循环的环的循环总和为负的情况。(如图情况) 思路:1.将从源点到其他各点的最短路设为无穷大, 源点处的距离为0;            2.利用Bellman-Ford求到各个点的最短路,需要循环n-1次(有n个顶点) 原因:如果假设该图没有负环存在,则最短经过每个点一次(即n-1条边),因此最多循环n-1次                          设图中的某两...

qq_41818544的博客 2892

2026年全国青少年信息素养大赛算法应用主题赛(C++赛项复赛模拟卷1:文末附答案)

2026年全国青少年信息素养大赛算法应用主题赛(C++赛项复赛模拟卷1:文末附答案)

王老师青少年编程 1613

利用Bellman-Ford算法(有向图) 判断负环

1 // 根据Bellman-Ford算法的原理 2 // 判断负环(算法的最大更新次数,应该是顶点数-1次) 3 // 而如果存在负环,算法会一直更新下去 4 5 // 我们根据循环进行的次数,来判断负环 6 7 #include <iostream> 8 #include <cstdio> 9 #include &lt...

饮闲的博客 1557

旗鱼优化算法(SFO)详解:从海洋猎手到智能优化

旗鱼优化算法(SFO)是一种新型群体智能优化算法,灵感来源于旗鱼的群体捕食行为。该算法采用双种群机制,模拟旗鱼(精英个体)与沙丁鱼(普通个体)的交互过程,通过交替攻击策略实现探索与开发的平衡。核心机制包括:基于猎物密度的旗鱼位置更新、随迭代衰减的攻击力度控制、以及捕食替换机制。SFO具有参数少、全局搜索能力强等特点,在高维复杂优化问题中表现优异。算法通过模拟自然界中的群体智能行为,为解决工程优化问题提供了新思路。

qq_42212808的博客 163

医学图像的对抗攻击:模型安全性与鲁棒性分析

医学图像的对抗攻击:模型安全性与鲁棒性分析 ,人工智能,计算机视觉,大模型,AI,本文围绕医学图像的对抗攻击展开,分析了其对AI模型的威胁。介绍了对抗样本定义、攻击原理,以及FGSM、BIM、PGD等常见攻击方法,还给出了相关代码示例。阐述了攻击对模型诊断准确性和可信度的影响,提出对抗训练、输入预处理、模型集成等提升模型安全性与鲁棒性的方法,探讨了评估指标、数据集和流程,分析了实际应用中的挑战与应对策略,最后展望了未来发展趋势。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 18万+

(C/C++)对具有负边的图实现Bellman-ford最短路径算法且判断是否具有负环

1.带负权值边的有向图中的最短路径路径问题 【问题描述】 对于一个带负权值边的有向图,实现Bellman-Ford算法, 求出从指定顶点s到其余顶点的最短路径,并判断图中是否存在负环。 例图 思路 使用dist[]数组存放每个结点距离起始点的距离,一共进行N-1次循环(因为一共有N个顶点,最多的路径也只有N-1条边),每次循环对每一条边进行一次update()。 在开始bellman-for...

周周的奇妙代码之旅 1049

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

C++图论基础Bellman-Ford与spfa算法如何判断负环

BF算法是暴力过 n - 1 轮、单趟全遍历边进行的松弛操作,他的最差情况就是至多会进行 n - 1 轮松弛操作,到第 n 轮肯定是松弛不了的,能松弛的就一定存在负环。状态转移方程:起点 ......................u——v 此时我们来算cnt[v],它等于刚刚经过的一条边加上在这条边之前所经过的边个数,这个在cnt[u]里面存着,即 cnt[v] = cnt[u] + 1。存在负环时,while循环会死循环,我们可以计数的方式,既可以判断负环,也可以跳出死循环。

江屿风的博客 854

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

判断负环

/*判断负环的两种方法:Spfa思想:如果存在一个点进入队列的次数超过N次,则存在负环。bellman_ford思想:对所有的边进行v-1松弛即如果dis[u]+map[u][v]<dis[v]则dis[v]=dis[u]+map[u][v]若v-1次松弛之后还能进行松弛,说明原图存在负环。复杂度0(VE)*///bellman_ford判断#in...

weixin_34198762的博客 290

Bellman-Ford && SPFA

Bellman-Ford Bellman-Ford算法基于边求解最短路,解决单源最短路问题,可以处理含负权边的图,判断是否存在负环。 图上的一条最短路径不超过V-1条边,每次遍历在前一次的基础上操作,是一个迭代松弛的过程。可以把由源点出发到各点的最短路径表示成一棵树,外层的每一次遍历操作就是将树的深度加深一层,内层遍历边执行松弛操作。(松弛:dist[i] = min( dist[...

120

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

  它是队列优化的Bellman-Ford算法。   优化的原理是:下一次松弛操作时被更新dis的点其实与上一次被更新的点有关!如果上一次被更新的点有一条边指向某点V,那么在下一次,点V就是可能被更新dis的点。   贴一个非常清晰的SPFA算法讲解:链接,很遗憾这个讲解没有说如何判断负环是否存在,我补充一下负环的判断方法。   第一种:     在算法更新完状态数组后,再遍历...

aibin6833的博客 248

King 差分约束 判负环

  给出n个不等式 给出四个参数第一个数i可以代表序列的第几项,然后给出n,这样前面两个数就可以描述为ai+a(i+1)+...a(i+n),即从i到n的连续和,再给出一个符号和一个ki当符号为gt代表‘>’,符号为lt代表‘<'那么样例可以表示1 2 gt 0a1+a2+a3>02 2 lt 2a2+a3+a4<2 求是否存在不等式使得ai+a(i+1)+a(i+2)...

weixin_30376163的博客 159

【判断负环】poj3259

【判断负环】poj3259

m0_71009069的博客 166

SPFA(某广为人知的最短路算法)总结

if(q.empty()||dis[to]&amp;amp;amp;amp;amp;amp;amp;gt;dis[q.front()]) q.push_back(to); else q.push_front(to);

qq_42702464的博客 781

【poj 3385】【模板】负环

题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个顶点,M条边 接下来M行,每行三个整数a b w,表示a->b有一条权值为w的边(若w<0则为单向,否则双向) 输出格式: 共T行。对于每组数据,存在负环则输出一行"YE5"(不含引号...

weixin_34212189的博客 86

代码随想录冲冲冲 Day59 图论Part10

这是基于之前Bellman_ford算法的一个优化,之前讲到可以通过n-1次来完全松弛得到答案。下一轮松弛的时候,就把队列里 que_size 个节点都弹出来,就是上一轮松弛入队列的节点。对于SPFA也是一样 用一个变量 que_size 记录每一轮松弛入队列的所有节点数量。如果是负权和了 那么Bellman_ford在n-1次松弛之后 数值依旧会变化。2.在que的基础上记录每个点的松弛次数 如果出现松弛次数=n 说明一定有环。1.直接松弛n次,在第n次观察是否还会变化 如果还会变化就是有环。

zzhzeel的博客 288

差分约束系统

负权最短路 链式前向星: //建图方式 int tot; int head[MAX_N]; struct node { int to, cost, next;} G[MAX_N * 2]; inline void add(int u, int v, int w) { ++ tot; G[tot].to = v; G[tot].cost = w; G[tot].next = head[u]; head[u] = tot; } //初始化方式 memset(head, -

weixin_51596558的博客 183

最短路径Bellman-Ford算法和SPFA算法详解

最短路径Bellman-Ford算法和SPFA算法详解

m0_72674633的博客 1685

SPFA判负环

知识点系列之---SPFA判负环

forever_dreams的博客 1万+
上一篇: uva658 - It's not a Bug, it's a Feature! 状态压缩+隐式图搜索+优先队列的dijkstra
下一篇: 差分约束系统
小小小小葱
博客等级 码龄14年 22粉丝 266原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值