forked from dimpeshpanwar/Java-Advance-Programs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjohnsonalgo.java
More file actions
160 lines (138 loc) · 4.88 KB
/
johnsonalgo.java
File metadata and controls
160 lines (138 loc) · 4.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/**
* Johnson's Algorithm (All-Pairs Shortest Paths)
* ----------------------------------------------
* Works for sparse graphs with negative edge weights (no negative cycles).
*
* Algorithm Steps:
* 1. Add a dummy node connected to all nodes with weight 0.
* 2. Run Bellman-Ford to compute vertex potentials (h values).
* 3. Reweight edges: w'(u, v) = w(u, v) + h[u] - h[v] (removes negatives).
* 4. Run Dijkstra from each vertex using reweighted edges.
* 5. Adjust distances back using h values.
*
* Time Complexity: O(V * (E log V))
* Space Complexity: O(V^2)
*
* Example use-case: Routing in networks with variable or negative costs.
*/
import java.util.*;
class JohnsonAlgorithm {
static class Edge {
int u, v, w;
Edge(int u, int v, int w) { this.u = u; this.v = v; this.w = w; }
}
static class Graph {
int V;
List<Edge> edges;
List<List<Edge>> adj;
Graph(int V) {
this.V = V;
edges = new ArrayList<>();
adj = new ArrayList<>();
for (int i = 0; i < V; i++)
adj.add(new ArrayList<>());
}
void addEdge(int u, int v, int w) {
edges.add(new Edge(u, v, w));
adj.get(u).add(new Edge(u, v, w));
}
}
// Bellman-Ford Algorithm to detect negative cycles and compute potentials
static int[] bellmanFord(Graph g, int src) {
int V = g.V;
int[] dist = new int[V];
Arrays.fill(dist, Integer.MAX_VALUE / 2);
dist[src] = 0;
// Relax edges |V|-1 times
for (int i = 1; i < V; i++) {
for (Edge e : g.edges) {
if (dist[e.u] + e.w < dist[e.v])
dist[e.v] = dist[e.u] + e.w;
}
}
// Check for negative weight cycle
for (Edge e : g.edges) {
if (dist[e.u] + e.w < dist[e.v]) {
System.out.println("Graph contains a negative weight cycle!");
return null;
}
}
return dist;
}
// Dijkstra using Priority Queue
static int[] dijkstra(List<List<Edge>> adj, int src) {
int V = adj.size();
int[] dist = new int[V];
Arrays.fill(dist, Integer.MAX_VALUE / 2);
dist[src] = 0;
PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[1]));
pq.offer(new int[]{src, 0});
while (!pq.isEmpty()) {
int[] cur = pq.poll();
int u = cur[0];
int d = cur[1];
if (d > dist[u]) continue;
for (Edge e : adj.get(u)) {
if (dist[u] + e.w < dist[e.v]) {
dist[e.v] = dist[u] + e.w;
pq.offer(new int[]{e.v, dist[e.v]});
}
}
}
return dist;
}
static void johnson(Graph g) {
int V = g.V;
// Step 1: Create an extended graph with a dummy vertex
Graph extended = new Graph(V + 1);
for (Edge e : g.edges)
extended.addEdge(e.u, e.v, e.w);
for (int v = 0; v < V; v++)
extended.addEdge(V, v, 0); // dummy node connected to all
// Step 2: Run Bellman-Ford from dummy node to get vertex potentials
int[] h = bellmanFord(extended, V);
if (h == null) return; // Negative cycle detected
// Step 3: Reweight edges in original graph
List<List<Edge>> newAdj = new ArrayList<>();
for (int i = 0; i < V; i++) newAdj.add(new ArrayList<>());
for (Edge e : g.edges) {
int newWeight = e.w + h[e.u] - h[e.v];
newAdj.get(e.u).add(new Edge(e.u, e.v, newWeight));
}
// Step 4: Run Dijkstra for each vertex
int[][] distMatrix = new int[V][V];
for (int u = 0; u < V; u++) {
int[] dist = dijkstra(newAdj, u);
for (int v = 0; v < V; v++) {
// Step 5: Convert back to original weights
if (dist[v] < Integer.MAX_VALUE / 2)
distMatrix[u][v] = dist[v] - h[u] + h[v];
else
distMatrix[u][v] = Integer.MAX_VALUE / 2;
}
}
// Print result
System.out.println("All-Pairs Shortest Path Matrix (Johnson's Algorithm):");
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (distMatrix[i][j] >= Integer.MAX_VALUE / 4)
System.out.print("INF\t");
else
System.out.print(distMatrix[i][j] + "\t");
}
System.out.println();
}
}
public static void main(String[] args) {
Graph g = new Graph(5);
g.addEdge(0, 1, -1);
g.addEdge(0, 2, 4);
g.addEdge(1, 2, 3);
g.addEdge(1, 3, 2);
g.addEdge(1, 4, 2);
g.addEdge(3, 2, 5);
g.addEdge(3, 1, 1);
g.addEdge(4, 3, -3);
johnson(g);
}
}