判断给定的有向图中是否存在负环。
利用 spfa算法判断负环有两种方法:
1)spfa 的 dfs形式,判断条件是存在一点在一条路径上出现多次。
2)spfa 的 bfs形式,判断条件是存在一点入队次数大于总顶点数。
代码如下:
法 1 (spfa的 dfs形式):
#include<iostream>
#include<cstdio>
#include<cstring>
usingnamespace std;
const intoo = 1 << 30;
const intmaxn = 1010;
structEdge {
int u, v, t, next;
}edge[2010];
intprev[maxn], p[maxn], d[maxn];
boolvis[maxn], flag;
inttot;
voidaddEdge(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 ++;
}
voidspfa(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("possiblen");
else printf("not possiblen");
}
return 0;
}
法 2 (spfa的 bfs形式):
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
usingnamespace std;
const intoo = 1 << 30;
const intmaxn = 1010;
structEdge {
int u, v, t, next;
}edge[2010];
intprev[maxn], p[maxn], d[maxn], in[maxn];
boolvis[maxn];
inttot;
queue<int> q;
voidaddEdge(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 ++;
}
boolspfa(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("possiblen");
else printf("not possiblen");
}
return 0;
}