package com.interview.algorithms.graph;
import com.interview.basics.model.graph.WeightedGraph;
import com.interview.basics.model.graph.WeightedGraph.Edge;
import com.interview.basics.model.graph.searcher.IndexedPriorityQueue;
import java.util.Stack;
/**
* Dijkstra Algorithm: Dynamic Programming
* Can represent the SPT with two vertex-indexed arrays:
* distTo[v] is length of shortest path from s to v.
* edgeTo[v] is last edge on shortest path from s to v.
* <p/>
* dist(s, t) = min(dist(s, t') + weight(t', t))
*
* @author stefanie
*
* skeleton:
* DIJKSTRA(G, w, s) //O((V+E)logE)
* INITIALIZE-SINGLE-SOURCE(G, s)
* S←Ø
* Q ← V[G] //V*O(1)
* while Q ≠ Ø
* do u ← EXTRACT-MIN(Q) //EXTRACT-MIN,V*O(V),V*O(lgV)
* S ← S ∪{u}
* for each vertex v ∈ Adj[u]
* do RELAX(u, v, w) //松弛技术,E*O(1),E*O(lgV)。
*/
public class C6_5_ShortestPath_Dijkstra2 {
WeightedGraph g;
double[] distTo;
Edge[] edgeTo;
IndexedPriorityQueue<Integer, Double> pq;
public C6_5_ShortestPath_Dijkstra2(WeightedGraph g) {
this.g = g;
init();
}
public void init() {
distTo = new double[g.V];
edgeTo = new Edge[g.V];
pq = new IndexedPriorityQueue<Integer, Double>();
for (int i = 0; i < g.V; i++) {
distTo[i] = Double.POSITIVE_INFINITY;
}
}
public void solve(int s) {
distTo[s] = 0.0;
pq.add(s, 0.0);
while (!pq.isEmpty()) {
int u = pq.poll();
if (g.adj[u] != null) {
for (Edge e : g.adj[u]) relax(e);
}
}
}
private void relax(Edge e) {
if (distTo[e.t] > distTo[e.s] + e.w) {
distTo[e.t] = distTo[e.s] + e.w;
edgeTo[e.t] = e;
if (pq.contains(e.t)) pq.update(e.t, distTo[e.t]);
else pq.add(e.t, distTo[e.t]);
}
}
public double distTo(int v) {
return distTo[v];
}
public boolean hasPathTo(int v) {
return distTo[v] < Double.POSITIVE_INFINITY;
}
public Iterable<Edge> pathTo(int v) {
if (!hasPathTo(v)) return null;
Stack<Edge> path = new Stack<Edge>();
for (Edge edge = edgeTo[v]; edge != null; edge = edgeTo[edge.s]) {
path.push(edge);
}
return path;
}
}