SPFA判负环|BFS|DFS

Posted ws_yzy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPFA判负环|BFS|DFS相关的知识,希望对你有一定的参考价值。

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

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

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

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

      代码如下:

 

 

 

 1 spfa  dfs 形式):

<span style="background-color: rgb(255, 255, 255);">#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;
</span>


 

 

 

 

 2 spfa  bfs 形式):

<span style="background-color: rgb(255, 255, 255);">#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;
</span>


CSDN 社区图书馆,开张营业! 深读计划,写书评领图书福利~

以上是关于SPFA判负环|BFS|DFS的主要内容,如果未能解决你的问题,请参考以下文章

论判短负环回路算法的存活率

洛谷P3385 模板负环 DFS-SPFA 判负环 图论

P3385 模板负环

[luogu3385]dfs_spfa判负环模板

Bellman-Ford

BZOJ1486HNOI2009最小圈 分数规划 dfs判负环。