博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spfa 判断负环 (转载)
阅读量:5231 次
发布时间:2019-06-14

本文共 2658 字,大约阅读时间需要 8 分钟。

当然,对于Spfa判负环,实际上还有优化:就是把判断单个点的入队次数大于n改为:如果总的点入队次数大于所有点两倍

时有负环,或者单个点的入队次数大于sqrt(点数)有负环。这样时间复杂度就降了很多了。

 

判断给定的有向图中是否存在负环。

      利用 spfa 算法判断负环有两种方法:

      1) spfa 的 dfs 形式,判断条件是存在一点在一条路径上出现多次。

      2) spfa 的 bfs 形式,判断条件是存在一点入队次数大于总顶点数。

      代码如下:

 

 

 

法 1 (spfa 的 dfs 形式):

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;

 

const int oo = 1 << 30;

const int maxn = 1010;

 

struct Edge {

     int u, v, t, next;

}edge[2010];

int prev[maxn], p[maxn], d[maxn];

bool vis[maxn], flag;

int tot;

 

void addEdge(int u, int v, int t) {

     edge[tot].u = u;

     edge[tot].v = v;

     edge[tot].t = t;

     edge[tot].next = prev[u];

     prev[u] = tot ++;

}

 

void spfa(int u) {

     int v;

    

     for (int i = prev[u]; i != -1; i = edge[i].next) {

         v = edge[i].v;

 

         if (d[u] + edge[i].t < d[v]) {

             if (vis[v]) {            //存在一点在一条路径上出现多次

                 flag = true;

                 return ;

             }

             else {

                 d[v] = d[u] + edge[i].t;

                 vis[v] = true;

                 spfa(v);   

             }

         }

     }

}

 

int main() {

     //freopen("input.txt", "r", stdin);

     //freopen("output.txt", "w", stdout);

    

     int T;

     int a, b, t;

     int n, m;

 

     scanf("%d", &T);

 

     while (T --) {

         scanf("%d%d", &n, &m);

        

         memset(prev, -1, sizeof(prev));

         tot = 0;

         for (int i = 1; i <= m; i ++) {

             scanf("%d%d%d", &a, &b, &t);

             addEdge(a, b, t);

         }

        

         memset(vis, false, sizeof(vis));

         fill(d, d + n, oo);

         d[0] = 0;

        

         flag = false;

        

         spfa(0);

        

         if (flag) printf("possible\n");

         else printf("not possible\n");

     }

 

     return 0;

}

 

 

 

 

法 2 (spfa 的 bfs 形式):

#include <iostream>

#include <cstdio>

#include <cstring>

#include <queue>

using namespace std;

 

const int oo = 1 << 30;

const int maxn = 1010;

 

struct Edge {

     int u, v, t, next;

}edge[2010];

int prev[maxn], p[maxn], d[maxn], in[maxn];

bool vis[maxn];

int tot;

queue<int> q;

 

void addEdge(int u, int v, int t) {

     edge[tot].u = u;

     edge[tot].v = v;

     edge[tot].t = t;

     edge[tot].next = prev[u];

     prev[u] = tot ++;

}

 

bool spfa(int n) {

     int u, v;

 

     while (!q.empty()) q.pop();

     memset(vis, false, sizeof(vis));

     memset(in, 0, sizeof(in));

     fill(d, d + n, oo);

    

     d[0] = 0; vis[0] = true;

     q.push(0);

    

     while (!q.empty()) {

         u = q.front();

         vis[u] = false;

         for (int i = prev[u]; i != -1; i = edge[i].next) {

             v = edge[i].v;

             if (d[u] + edge[i].t < d[v]) {

                 d[v] = d[u] + edge[i].t;

                

                 if (!vis[v]) {

                     in[v] ++;

 

                     if (in[v] > n) return true;                //存在一点入队次数大于总顶点数

 

                     vis[v] = true;

                     q.push(v);

                 }

             }

         }

        

         vis[u] = false;

         q.pop();

     }

 

     return false;

}

 

int main() {

     //freopen("input.txt", "r", stdin);

     //freopen("output.txt", "w", stdout);

    

     int T;

     int a, b, t;

     int n, m;

 

     scanf("%d", &T);

 

     while (T --) {

         scanf("%d%d", &n, &m);

        

         memset(prev, -1, sizeof(prev));

         tot = 0;

         for (int i = 1; i <= m; i ++) {

             scanf("%d%d%d", &a, &b, &t);

             addEdge(a, b, t);

         }

        

         if (spfa(n)) printf("possible\n");

         else printf("not possible\n");

     }

 

     return 0;

 

}

 

转载于:https://www.cnblogs.com/zhangmingcheng/p/3791510.html

你可能感兴趣的文章
Nginx配置文件(nginx.conf)配置详解1
查看>>
linux php编译安装
查看>>
name phone email正则表达式
查看>>
721. Accounts Merge
查看>>
OpenCv-Python 图像处理基本操作
查看>>
「Unity」委托 将方法作为参数传递
查看>>
重置GNOME-TERMINAL
查看>>
redis哨兵集群、docker入门
查看>>
hihoCoder 1233 : Boxes(盒子)
查看>>
团队的绩效评估计划
查看>>
oracle中anyData数据类型的使用实例
查看>>
C++对vector里面的元素排序及取任意重叠区间
查看>>
软件测试——性能测试总结
查看>>
12.4站立会议
查看>>
Java Concurrentmodificationexception异常原因和解决方法
查看>>
Python 面向对象(其四)
查看>>
客户端访问浏览器的流程
查看>>
codeforces水题100道 第二十二题 Codeforces Beta Round #89 (Div. 2) A. String Task (strings)
查看>>
c++||template
查看>>
[BZOJ 5323][Jxoi2018]游戏
查看>>