zoukankan      html  css  js  c++  java
  • 浅谈SPFA判负环

    SPFA判负环

    有不足的地方请指出
    本蒟蒻一定会修改吼

    【前言】

    最短路的求法中最广为人知的我仅仅知道的,有弗洛伊德,dijkstra和SPFA。
    弗洛伊德最简单的三重循环,复杂度n^3,一般也就做个n小的题目,遇到n大一点的(超过1000)几乎就只能拿部分分。
    SPFA是一种广为人知的已经死掉的算法(某人说过一道图论题如果不卡卡SPFA就不是一道好的图论题目),但是他却有一个很重要的作用,是其他三者无法代替的,那就是这篇博客的题目,判负环!
    dijkstra是这三种里面最为稳定的一种算法,何为稳定,弗洛伊德只能跑那么小的数据范围就可以看出来,在很多题目上面只能打一下暴力,SPFA就更不用多说了他死了,所以dijkstra理所当然的成为了最稳定的算法。

    说这么多就是为了引出SPFA判负环!

    【不可代替性】

    dijkstra和弗洛伊德都是判断不了负环的
    弗洛伊德可以判断负环
    但是我不会
    我也不想会
    人家SPFA好不容易有一个活着的理由干嘛要给人家扼杀掉
    dijkstra遇到负权边就死了
    更别说负环了
    但是SPFA可以判断负环
    具体原因不多赘述了,学过dijkstra和弗洛伊德的应该都知道
    但是我不知道

    【具体实现】

    SPFA的过程

    每次都拿一个点到起点的距离来松弛其他的点到起点的距离

    判负环

    负环是一个边权值和等于负数的环
    可以想想一下
    如果SPFA遇到了负环会出现什么情况
    一直松弛下去
    因为每次出现的负数都可以让目前最短的边变得更短
    所以可以根据这一点
    开一个数组用来记录这是这一条链上第几个入队的数
    然后每次松弛的时候都把到达的点入队的数标为前面这个点入队的次数+1,因为这是一个顺序的过程
    就像是1,2,3……这样的数列
    然后如果出现了负环就会和上面说的一样一直松弛下去
    然后这个负环上的点入队的数就会不断变大
    可以想一下
    如果n个数连成一个点
    那入队数最大才只能是n
    所以只要某个点的入队数大于了n
    那就可以证明他在不停得松弛
    也就是出现了负环

    【核心代码】

    bool SPFA(int acioi)
    {
    	queue<int>q;
    	for(register int i = 1;i <= n;++ i)
    		d[i] = 99999999;
    	d[acioi] = 0;
    	q.push(acioi);
    	while(!q.empty())
    	{
    		int x = q.front();
    		q.pop();use[x] = false;
    		for(register int i = head[x];i != 0;i = a[i].ne)
    		{
    			int y = a[i].y;
    			if(d[y] > d[x] + a[i].z)
    			{
    				d[y] = d[x] + a[i].z;
    				cnt[y] = cnt[x] + 1;
    				if(cnt[y] > n)
    					return false;
    				if(use[y] == false)
    				{
    					use[y] = true;
    					q.push(y);
    				}
    			}
    		}
    	}
    	return true;
    }
    

    【例题】

    洛谷P2136 拉近距离
    SPFA判负环板子题
    详情解释请看
    这里

    洛谷P3385 【模板】负环
    同样也是板子题
    想请解释请看
    这里

  • 相关阅读:
    webmagic使用
    网站文件下载链接
    正则表达式
    JS 页面刷新或重载
    History
    【问题&解决】fonts/fontawesome-webfont.woff2 404 (Not Found)
    ckeditor的使用
    Windows Server 2012 R2 或 2016 无法安装 .Net 3.5.1
    自定义配置文件的读取
    MVC中上传文件大小限制的解决办法
  • 原文地址:https://www.cnblogs.com/acioi/p/11694294.html
Copyright © 2011-2022 走看看