import
java.util.ArrayList;
import
java.util.Arrays;
public
class
Graph {
private
static
class
Neighbour {
int
destination;
int
weight;
Neighbour(
int
destination,
int
weight)
{
this
.destination = destination;
this
.weight = weight;
}
}
private
int
vertices;
private
final
ArrayList<ArrayList<Neighbour> >
adjacencyList;
public
Graph(
int
vertices)
{
this
.vertices = vertices;
adjacencyList =
new
ArrayList<>(vertices);
for
(
int
i =
0
; i < vertices; i++)
adjacencyList.add(
new
ArrayList<>());
}
public
Graph(
int
vertices,
int
[][] adjacencyMatrix)
{
this
(vertices);
for
(
int
i =
0
; i < vertices; i++) {
for
(
int
j =
0
; j < vertices; j++) {
if
(adjacencyMatrix[i][j] !=
0
)
addEdge(i, j, adjacencyMatrix[i][j]);
}
}
}
public
void
addEdge(
int
source,
int
destination,
int
weight)
{
adjacencyList.get(source).add(
new
Neighbour(destination, weight));
}
public
int
[] dijkstra(
int
source)
{
boolean
[] isVisited =
new
boolean
[vertices];
int
[] distance =
new
int
[vertices];
Arrays.fill(distance, Integer.MAX_VALUE);
distance =
0
;
for
(
int
vertex =
0
; vertex < vertices; vertex++) {
int
minDistanceVertex = findMinDistanceVertex(
distance, isVisited);
isVisited[minDistanceVertex] =
true
;
for
(Neighbour neighbour :
adjacencyList.get(minDistanceVertex)) {
int
destination = neighbour.destination;
int
weight = neighbour.weight;
if
(!isVisited[destination]
&& distance[minDistanceVertex] + weight
< distance[destination])
distance[destination]
= distance[minDistanceVertex]
+ weight;
}
}
return
distance;
}
private
int
findMinDistanceVertex(
int
[] distance,
boolean
[] isVisited)
{
int
minIndex = -
1
,
minDistance = Integer.MAX_VALUE;
for
(
int
vertex =
0
; vertex < vertices; vertex++) {
if
(!isVisited[vertex]
&& distance[vertex] <= minDistance) {
minDistance = distance[vertex];
minIndex = vertex;
}
}
return
minIndex;
}
public
int
[] bellmanford(
int
source)
{
int
[] distance =
new
int
[vertices];
Arrays.fill(distance, Integer.MAX_VALUE);
distance =
0
;
for
(
int
i =
0
; i < vertices -
1
; i++) {
for
(
int
currentVertex =
0
;
currentVertex < vertices;
currentVertex++) {
for
(Neighbour neighbour :
adjacencyList.get(currentVertex)) {
if
(distance[currentVertex]
!= Integer.MAX_VALUE
&& distance[currentVertex]
+ neighbour.weight
< distance
[neighbour
.destination]) {
distance[neighbour.destination]
= distance[currentVertex]
+ neighbour.weight;
}
}
}
}
for
(
int
currentVertex =
0
;
currentVertex < vertices; currentVertex++) {
for
(Neighbour neighbour :
adjacencyList.get(currentVertex)) {
if
(distance[currentVertex]
!= Integer.MAX_VALUE
&& distance[currentVertex]
+ neighbour.weight
< distance[neighbour
.destination])
return
null
;
}
}
return
distance;
}
public
int
[][] johnsons()
{
this
.vertices++;
adjacencyList.add(
new
ArrayList<>());
for
(
int
i =
0
; i < vertices -
1
; i++)
adjacencyList.get(vertices -
1
)
.add(
new
Neighbour(i,
0
));
int
[] h = bellmanford(vertices -
1
);
if
(h ==
null
)
return
null
;
for
(
int
u =
0
; u < vertices; u++) {
ArrayList<Neighbour> neighbours
= adjacencyList.get(u);
for
(Neighbour neighbour : neighbours) {
int
v = neighbour.destination;
int
w = neighbour.weight;
neighbour.weight = w + h[u] - h[v];
}
}
adjacencyList.remove(vertices -
1
);
vertices--;
int
[][] distances =
new
int
[vertices][];
for
(
int
s =
0
; s < vertices; s++)
distances[s] = dijkstra(s);
for
(
int
u =
0
; u < vertices; u++) {
for
(
int
v =
0
; v < vertices; v++) {
if
(distances[u][v] == Integer.MAX_VALUE)
continue
;
distances[u][v] += (h[v] - h[u]);
}
}
return
distances;
}
public
static
void
main(String[] args)
{
final
int
vertices =
4
;
final
int
[][] matrix = { {
0
,
0
, -
2
,
0
},
{
4
,
0
,
3
,
0
},
{
0
,
0
,
0
,
2
},
{
0
, -
1
,
0
,
0
} };
Graph graph =
new
Graph(vertices, matrix);
int
[][] distances = graph.johnsons();
if
(distances ==
null
) {
System.out.println(
"Negative weight cycle detected."
);
return
;
}
System.out.println(
"Distance matrix:"
);
System.out.print(
" \t"
);
for
(
int
i =
0
; i < vertices; i++)
System.out.printf(
"%3d\t"
, i);
for
(
int
i =
0
; i < vertices; i++) {
System.out.println();
System.out.printf(
"%3d\t"
, i);
for
(
int
j =
0
; j < vertices; j++) {
if
(distances[i][j] == Integer.MAX_VALUE)
System.out.print(
" X\t"
);
else
System.out.printf(
"%3d\t"
,
distances[i][j]);
}
}
}
}