Finding a negative cycle in the graph¶
You are given a directed weighted graph
In another formulation of the problem you have to find all pairs of vertices which have a path of arbitrarily small weight between them.
It is convenient to use different algorithms to solve these two variations of the problem, so we'll discuss both of them here.
Using Bellman-Ford algorithm¶
Bellman-Ford algorithm allows you to check whether there exists a cycle of negative weight in the graph, and if it does, find one of these cycles.
The details of the algorithm are described in the article on the Bellman-Ford algorithm. Here we'll describe only its application to this problem.
The standard implementation of Bellman-Ford looks for a negative cycle reachable from some starting vertex
Do
Implementation¶
struct Edge {
int a, b, cost;
};
int n;
vector<Edge> edges;
const int INF = 1000000000;
void solve() {
vector<int> d(n, 0);
vector<int> p(n, -1);
int x;
for (int i = 0; i < n; ++i) {
x = -1;
for (Edge e : edges) {
if (d[e.a] + e.cost < d[e.b]) {
d[e.b] = max(-INF, d[e.a] + e.cost);
p[e.b] = e.a;
x = e.b;
}
}
}
if (x == -1) {
cout << "No negative cycle found.";
} else {
for (int i = 0; i < n; ++i)
x = p[x];
vector<int> cycle;
for (int v = x;; v = p[v]) {
cycle.push_back(v);
if (v == x && cycle.size() > 1)
break;
}
reverse(cycle.begin(), cycle.end());
cout << "Negative cycle: ";
for (int v : cycle)
cout << v << ' ';
cout << endl;
}
}
Using Floyd-Warshall algorithm¶
The Floyd-Warshall algorithm allows to solve the second variation of the problem - finding all pairs of vertices
Again, the details can be found in the Floyd-Warshall article, and here we describe only its application.
Run Floyd-Warshall algorithm on the graph.
Initially -INF
.
Implementation¶
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
for (int t = 0; t < n; ++t) {
if (d[i][t] < INF && d[t][t] < 0 && d[t][j] < INF)
d[i][j] = - INF;
}
}
}