JavaAlgorithms/DataStructures/Graphs/BellmanFord.java
2021-04-18 18:02:48 +08:00

162 lines
4.8 KiB
Java

package DataStructures.Graphs;
import java.util.*;
class BellmanFord
/*Implementation of Bellman ford to detect negative cycles. Graph accepts inputs in form of edges which have
start vertex, end vertex and weights. Vertices should be labelled with a number between 0 and total number of vertices-1,both inclusive*/
{
int vertex, edge;
private Edge edges[];
private int index = 0;
BellmanFord(int v, int e) {
vertex = v;
edge = e;
edges = new Edge[e];
}
class Edge {
int u, v;
int w;
/**
* @param u Source Vertex
* @param v End vertex
* @param c Weight
*/
public Edge(int a, int b, int c) {
u = a;
v = b;
w = c;
}
}
/**
* @param p[] Parent array which shows updates in edges
* @param i Current vertex under consideration
*/
void printPath(int p[], int i) {
if (p[i] == -1) // Found the path back to parent
return;
printPath(p, p[i]);
System.out.print(i + " ");
}
public static void main(String args[]) {
BellmanFord obj = new BellmanFord(0, 0); // Dummy object to call nonstatic variables
obj.go();
}
public void
go() // Interactive run for understanding the class first time. Assumes source vertex is 0 and
// shows distance to all vertices
{
Scanner sc = new Scanner(System.in); // Grab scanner object for user input
int i, v, e, u, ve, w, j, neg = 0;
System.out.println("Enter no. of vertices and edges please");
v = sc.nextInt();
e = sc.nextInt();
Edge arr[] = new Edge[e]; // Array of edges
System.out.println("Input edges");
for (i = 0; i < e; i++) {
u = sc.nextInt();
ve = sc.nextInt();
w = sc.nextInt();
arr[i] = new Edge(u, ve, w);
}
int dist[] =
new int
[v]; // Distance array for holding the finalized shortest path distance between source
// and all vertices
int p[] = new int[v]; // Parent array for holding the paths
for (i = 0; i < v; i++) dist[i] = Integer.MAX_VALUE; // Initializing distance values
dist[0] = 0;
p[0] = -1;
for (i = 0; i < v - 1; i++) {
for (j = 0; j < e; j++) {
if ((int) dist[arr[j].u] != Integer.MAX_VALUE
&& dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
dist[arr[j].v] = dist[arr[j].u] + arr[j].w; // Update
p[arr[j].v] = arr[j].u;
}
}
}
// Final cycle for negative checking
for (j = 0; j < e; j++)
if ((int) dist[arr[j].u] != Integer.MAX_VALUE && dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
neg = 1;
System.out.println("Negative cycle");
break;
}
if (neg == 0) // Go ahead and show results of computation
{
System.out.println("Distances are: ");
for (i = 0; i < v; i++) System.out.println(i + " " + dist[i]);
System.out.println("Path followed:");
for (i = 0; i < v; i++) {
System.out.print("0 ");
printPath(p, i);
System.out.println();
}
}
sc.close();
}
/**
* @param source Starting vertex
* @param end Ending vertex
* @param Edge Array of edges
*/
public void show(
int source,
int end,
Edge arr[]) // Just shows results of computation, if graph is passed to it. The graph should
// be created by using addEdge() method and passed by calling getEdgeArray() method
{
int i, j, v = vertex, e = edge, neg = 0;
double dist[] =
new double
[v]; // Distance array for holding the finalized shortest path distance between source
// and all vertices
int p[] = new int[v]; // Parent array for holding the paths
for (i = 0; i < v; i++) dist[i] = Integer.MAX_VALUE; // Initializing distance values
dist[source] = 0;
p[source] = -1;
for (i = 0; i < v - 1; i++) {
for (j = 0; j < e; j++) {
if ((int) dist[arr[j].u] != Integer.MAX_VALUE
&& dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
dist[arr[j].v] = dist[arr[j].u] + arr[j].w; // Update
p[arr[j].v] = arr[j].u;
}
}
}
// Final cycle for negative checking
for (j = 0; j < e; j++)
if ((int) dist[arr[j].u] != Integer.MAX_VALUE && dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
neg = 1;
System.out.println("Negative cycle");
break;
}
if (neg == 0) // Go ahead and show results of computaion
{
System.out.println("Distance is: " + dist[end]);
System.out.println("Path followed:");
System.out.print(source + " ");
printPath(p, end);
System.out.println();
}
}
/**
* @param x Source Vertex
* @param y End vertex
* @param z Weight
*/
public void addEdge(int x, int y, int z) // Adds unidirectional edge
{
edges[index++] = new Edge(x, y, z);
}
public Edge[] getEdgeArray() {
return edges;
}
}