Breadth First Search
Download
Report
Transcript Breadth First Search
Nattee Niparnan
SHORTEST PATH
Graph with Length
Dijkstra’s Algorithm
Edge with Length
Length function
l(a,b) = distance
from a to b
Finding Shortest Path
BFS can give us the shortest path
Just convert the length edge into unit edge
However, this is very slow
Imagine a case when the length is 1,000,000
Alarm Clock Analogy
No need to walk to every node
Since it won’t change
anything
We skip to the “actual” node
Set up the clock at alarm at the
target node
Alarm Clock Algorithm
Set an alarm clock for node s at time 0.
Repeat until there are no more alarms:
Say the next alarm goes off at time T, for node u.
Then:
The distance from s to u is T.
For each neighbor v of u in G:
If there is no alarm yet for v, set one for time T + l(u, v).
If v's alarm is set for later than T + l(u, v), then reset it to
this earlier time.
Dijkstra’s Algo from BFS
procedure dijkstra(G, l, s)
//Input: Graph G = (V;E), directed or undirected; vertex s V;
positive edge lengths l
// Output: For all vertices u reachable from s, dist[u] is set
to the distance from s to u.
for all v V
dist[v] = +
prev[v] = nil
dist[s] = 0
Priority_Queue H = makequeue(V) // enqueue all vertices (using
dist as keys)
while H is not empty
v = H.deletemin()
for each edge (v,u) E
if dist[u] > dist[v] + l(v, u)
dist[u] = dist[v] + l(v, u)
prev[u] = v
H.decreasekey(v,dist[v]) // change the value of v to dist[v]
Another Implementation of
Dijkstra’s
Growing from Known Region of shortest path
Given a graph and a starting node s
What if we know a shortest path from s to some
subset S’ V?
Divide and Conquer Approach?
Dijktra’s Algo #2
procedure dijkstra(G, l, s)
//Input: Graph G = (V;E), directed or undirected; vertex s V;
positive edge lengths l
// Output: For all vertices u reachable from s, dist[u] is set
to the distance from s to u.
for all u V :
dist[u] = +
prev[u] = nil
dist[s] = 0
R = {}
// (the “known region”)
while R ≠ V :
Pick the node v R with smallest dist[]
Add v to R
for all edges (v,u) E:
if dist[u] > dist[v] + l(v,u)
dist[u] = dist[v] + l(v,u)
prev[u] = v
Analysis
There are |V| ExtractMin
Need to check all edges
At most |E|, if we use adjacency list
Maybe |V2|, if we use adjacency matrix
Value of dist[] might be changed
Depends on underlying data structure
Choice of DS
Using simple array
Each ExtractMin uses O(V)
Each change of dist[] uses O(1)
Result = O(V2 + E) = O(V2)
Using binary heap
Might be V2
Each ExtractMin uses O(lg V)
Each change of dist[] uses O(lg V)
Result = O( (V + E) lg V)
Can be O (V2 lg V)
Good when
the graph is
sparse
Fibonacci Heap
Using simple array
Each ExtractMin uses O( lg V) (amortized)
Each change of dist[] uses O(1) (amortized)
Result = O(V lg V + E)
Graph with Negative Edge
Disjktra’s works because a shortest path to v
must pass throught a node closer than v
Shortest path to A pass through B which is…
in BFS sense… is further than A
Negative Cycle
A graph with a negative cycle has no shortest
path
The shortest.. makes no sense..
Hence, negative edge must be a directed
Key Idea in Shortest Path
Update the distance
if (dist[z] > dist[v] + l(v,z))
dist[z] = dist[v] + l(v,z)
This is safe to perform
Another Approach to Shortest
Path
A shortest path must has at most |V| - 1 edges
Writing a recurrent
d(n, v) = shortest distance from s to v using
at most n edges
d(n,v) = min of
d(n – 1, v)
min( d(n – 1, u) + l(u,v) )
over all edges
(u,v)
Initial d(*,s) = 0, d(|V| - 1,v) = inf
Bellman-Ford Algorithm
Dynamic Programming
Since d(n,*) use d(n – 1,*), we use only 1D
array to store D
Bellman-Ford Algorithm
procedure BellmanFord(G, l, s)
//Input: Graph G = (V,E), directed; vertex s V; edge lengths l
(may be negative), no negative cycle
// Output: For all vertices u reachable from s, dist[u] is set
to the distance from s to u.
for all u V :
dist[u] = +
prev[u] = nil
dist[s] = 0
repeat |V| - 1 times:
for all edges (a,b) E:
if dist[b] > dist[a] + l(a,b)
dist[b] = dist[a] + l(a,b)
prev[b] = a
Analysis
Very simple
Loop |V| times
Each loop takes |E| iterations
O(V E)
Dense graph O(V3)
Bellman-Ford is slower but can detect
negative cycle
Detecting Negative Cycle
After repeat the loop |V|-1 times
If we can still do
dist[v] = dist[u] + l(y,v)
Then, there is a negative cycle
Because there is a shorter path eventhough we
have repeat this |V|-1 time
for all edges (a,b) E
if dist[b] > dist[a] + l(a,b)
printf(“negative cycle\n”)
Shortest Path in DAG
Path in DAG appears in linearized order
procedure dag-shortest-path(G, l, s)
//Input: DAG G = (V;E), vertex s V; edge lengths l (may be
negative)
// Output: For all vertices u reachable from s, dist[u] is set
to the distance from s to u.
for all u V :
dist[u] = +
prev[u] = nil
dist[s] = 0
Linearize G
For each u V , in linearized order:
for all edges (u,v) E:
if dist[v] > dist[u] + l(u,v)
dist[v] = dist[u] + l(y,v)
prev[b] = a
All Pair Shortest Path
All Pair Shortest Path
Problem
Input:
A graph
Output:
A matrix D[1..v,1..v] giving the shortest distance
between every pair of vertices
Approach
Standard shortest path gives shortest path
from a given vertex s to every vertex
Repeat this for every starting vertex s
Dijkstra O(|V| * (|E| log |V|) )
Bellman-Ford O(|V| * (|V|3) )
Dynamic Algorithm Approach
Floyd-Warshall
Dynamic Algorithm Approach
Using the previous recurrent
d(n, v) = shortest distance from s to v using at
most n edges
Change to
dn(a,b) = shortest distance from a to b using at most
n edges
dn(a,b) = min of
dn-1(a,b)
min(dn-1(a,k) + l(k,b) ) over all edges (k,b)
Initial d0(a,a) = 0, d0 (a,b) = inf , d1(a,b) = l(a,b)
Dynamic Algorithm Approach
Again, A shortest path must has at most |V| -
1 edges
What we need to find is d|V|(a,b)
Let D{M} be the matrix dm(a,b)
Start with D{1} and compute D{2}
Similar to computation of dist[] in Bellman-Ford
Repeat until we have D{|V|}
Floyd-Warshall
Use another recurrent
dk(a,b) is a shortest distance from a to b that
can travel via a set of vertex {1,2,3,…,k}
d0(a,b) = l(a,b) because it can not go pass any
vertex
d1(a,b) means a shortest distance that the
path can have only vertex 1 (not including a
and b)
Recurrent Relation
dk(a,b) = min of
dk-1(a,b)
dk-1(a,k) + dk-1 (k,b)
Initial d0(a,b) = l(a,b)
Floyd-Warshall
procedure FloydWarshall(G, l)
//Input: Graph G = (V,E); vertex s V; edge lengths l (may be
negative), no negative cycle
// Output: dist[u,v] is the shortest distance from u to v.
dist = l
for k = 0 to |V| - 1
for i = 0 to |V| - 1
for j = 0 to |V| - 1
dist[i][j] = min (dist[i][j],
dist[i][k] + dist[k][j])
Analysis
Very simple
3 nested loops of |V|
O(|V|3)