programming-examples/java/Data_Structures/BellmanFord.java

92 lines
2.2 KiB
Java
Raw Normal View History

2019-11-15 12:59:38 +01:00
import java.util.*;
import java.util.stream.Stream;
public class BellmanFord {
static final int INF = Integer.MAX_VALUE / 2;
public static class Edge {
int v, cost;
public Edge(int v, int cost) {
this.v = v;
this.cost = cost;
}
}
public static boolean bellmanFord(List<Edge>[] graph, int s, int[] dist, int[] pred) {
Arrays.fill(pred, -1);
Arrays.fill(dist, INF);
dist[s] = 0;
int n = graph.length;
boolean updated = false;
for (int step = 0; step < n; step++) {
updated = false;
for (int u = 0; u < n; u++) {
if (dist[u] == INF) continue;
for (Edge e : graph[u]) {
if (dist[e.v] > dist[u] + e.cost) {
dist[e.v] = dist[u] + e.cost;
dist[e.v] = Math.max(dist[e.v], -INF);
pred[e.v] = u;
updated = true;
}
}
}
if (!updated)
break;
}
// if updated is true then a negative cycle exists
return updated == false;
}
public static int[] findNegativeCycle(List<Edge>[] graph) {
int n = graph.length;
int[] pred = new int[n];
Arrays.fill(pred, -1);
int[] dist = new int[n];
int last = -1;
for (int step = 0; step < n; step++) {
last = -1;
for (int u = 0; u < n; u++) {
if (dist[u] == INF) continue;
for (Edge e : graph[u]) {
if (dist[e.v] > dist[u] + e.cost) {
dist[e.v] = Math.max(dist[u] + e.cost, -INF);
dist[e.v] = Math.max(dist[e.v], -INF);
pred[e.v] = u;
last = e.v;
}
}
}
if (last == -1)
return null;
}
for (int i = 0; i < n; i++) {
last = pred[last];
}
int[] p = new int[n];
int cnt = 0;
for (int u = last; u != last || cnt == 0; u = pred[u]) {
p[cnt++] = u;
}
int[] cycle = new int[cnt];
for (int i = 0; i < cycle.length; i++) {
cycle[i] = p[--cnt];
}
return cycle;
}
// Usage example
public static void main(String[] args) {
List<Edge>[] graph = Stream.generate(ArrayList::new).limit(4).toArray(List[]::new);
graph[0].add(new Edge(1, 1));
graph[1].add(new Edge(0, 1));
graph[1].add(new Edge(2, 1));
graph[2].add(new Edge(3, -10));
graph[3].add(new Edge(1, 1));
int[] cycle = findNegativeCycle(graph);
System.out.println(Arrays.toString(cycle));
}
}