import java.util.*;
import sk.upjs.paz.graph.*;
public class Grafy {
// Relaxacia orientovanej hrany
public static void relax(Edge e, Map<Vertex, Double> d,
Map<Vertex, Vertex> predchodca) {
Vertex u = e.getSource();
Vertex v = e.getTarget();
if (d.get(u) + e.getWeight() < d.get(v)) {
d.put(v, d.get(u) + e.getWeight());
predchodca.put(v, u);
}
}
// Bellman-Fordov algoritmus
public static Map<Vertex, Double> bellmanFord(Graph g, Vertex s,
Map<Vertex, Vertex> predchodca) {
// Iba orientovane grafy su akceptovane ako vstup
if (!g.isDirected())
throw new RuntimeException(
"Len orientovane grafy su akceptovane pre Bellman-Fordov algoritmus");
predchodca.clear();
// Vytvorime map, v ktorom budeme pre kazdy vrchol udrziavat aktualny
// horny odhad dlzky najkratsej cesty z s do tohto vrcholu
Map<Vertex, Double> d = new HashMap<Vertex, Double>();
// Inicializacia predbeznych najkratsich vzdialenosti
for (Vertex v : g.getVertices())
d.put(v, Double.POSITIVE_INFINITY);
d.put(s, 0d);
// n-krat opakujeme relaxaciu vsetkych hran
for (int i = 0; i < g.getVertices().size(); i++)
for (Edge e : g.getEdges())
relax(e, d, predchodca);
return d;
}
public static List<Vertex> cestaDo(Vertex odkial, Vertex kam,
Map<Vertex, Double> d) {
List<Vertex> cesta = new ArrayList<Vertex>();
Vertex aktualny = kam;
while (aktualny != odkial) {
cesta.add(aktualny);
for (Edge h : aktualny.getInEdges())
if (d.get(h.getSource()) + h.getWeight() == d.get(aktualny)) {
aktualny = h.getSource();
break;
}
}
cesta.add(aktualny);
Collections.reverse(cesta);
return cesta;
}
public static List<Vertex> cestaDo2(Vertex odkial, Vertex kam,
Map<Vertex, Vertex> predchodca) {
List<Vertex> cesta = new ArrayList<Vertex>();
Vertex aktualny = kam;
while (aktualny != odkial) {
cesta.add(aktualny);
aktualny = predchodca.get(aktualny);
}
cesta.add(aktualny);
Collections.reverse(cesta);
return cesta;
}
public static double[][] grafNaMaticu(Graph g) {
// Vyrobime pole vrcholov
Vertex[] vrcholy = new Vertex[g.getVertices().size()];
int idx = 0;
for (Vertex v : g.getVertices()) {
vrcholy[idx] = v;
idx++;
}
System.out.println(Arrays.toString(vrcholy));
// Vyrobime pole, do ktoreho budeme davat vzajomne vzdialenosti
double[][] d = new double[vrcholy.length][vrcholy.length];
for (int i = 0; i < vrcholy.length; i++)
for (int j = 0; j < vrcholy.length; j++)
if (g.hasEdge(vrcholy[i], vrcholy[j]))
d[i][j] = g.getEdge(vrcholy[i], vrcholy[j]).getWeight();
else
d[i][j] = Double.POSITIVE_INFINITY;
return d;
}
// Dijkstrov algoritmus
public static double[] dijkstra(double[][] g, int startIdx) {
double[] d = new double[g.length];
Arrays.fill(d, Double.POSITIVE_INFINITY);
d[startIdx] = 0;
boolean[] nevybavene = new boolean[g.length];
Arrays.fill(nevybavene, true);
int pocetNevybavenych = g.length;
while (pocetNevybavenych > 0) {
// Vyberieme vrchol, ktory spomedzi nevybavenych ma najmensi
// medzivysledok d
double min = Double.MAX_VALUE;
int idx = -1;
for (int i = 0; i < d.length; i++) {
if (nevybavene[i]) {
if (d[i] < min) {
min = d[i];
idx = i;
}
}
}
// Nechame zrelaxovat vsetky z neho vychadzajuce hrany
for (int j = 0; j < g.length; j++)
if (d[idx] + g[idx][j] < d[j])
d[j] = d[idx] + g[idx][j];
// Vybrany vrchol vyberieme z mnoziny nevybavenych
nevybavene[idx] = false;
pocetNevybavenych--;
}
return d;
}
public static void main(String[] args) {
Graph mapa = new Graph();
mapa.loadFromFile("graf.txt");
mapa.setDirected(true);
Map<Vertex, Vertex> predchodca = new HashMap<Vertex, Vertex>();
Map<Vertex, Double> d = bellmanFord(mapa, mapa.getVertex("A"),
predchodca);
System.out.println(d);
System.out
.println(cestaDo(mapa.getVertex("A"), mapa.getVertex("G"), d));
System.out.println(cestaDo2(mapa.getVertex("A"), mapa.getVertex("G"),
predchodca));
double [][] matica = grafNaMaticu(mapa);
System.out.println(Arrays.toString(dijkstra(matica, 0)));
}
}