Breadth First Search
Download
Report
Transcript Breadth First Search
Nattee Niparnan
GRAPH ALGORITHM:
BREADTH FIRST SEARCH
Distance of nodes
The distance between two nodes is the
length of the shortest path between them
SA 1
SC 1
SB 2
DFS and Length
DFS finds all nodes reachable from the
starting node
But it might not be “visited” according to the
distance
Ball and Strings
We can compute distance by
proceeding from “layer” to “layer”
Shortest Path Problem (Undi,
Unit)
Input:
A graph, undirected
A starting node S
Output:
A label on every node, giving the distance from S
to that node
Breadth-First-Search
Visit node according to its layer
procedure bfs(G; s)
//Input: Graph G = (V,E), directed or undirected; vertex s V
//Output: visit[u] is set to true for all nodes u reachable from v
for all u V :
visit[u] = false
visit[s] = true
Queue Q = [s] (queue containing just s)
while Q is not empty:
u = eject(Q)
previsit(u)
visit[u] = true;
for all edges (u,v) E:
if visit[v] = false:
visit[v] = true;
inject(Q,v);
postvisit(u)
Distance using BFS
procedure shortest_bfs(G, s)
//Input: Graph G = (V,E), directed or undirected; vertex s V
//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] = -1
dist[s] = 0
Queue Q = [s] (queue containing just s)
while Q is not empty:
u = eject(Q);
for all edges (u,v) E:
if dist[v] = -1:
inject(Q,v);
dist[v] = dist[u] + 1;
Use dist as visit
DFS by Stack
procedure dfs(G, s)
//Input: Graph G = (V,E), directed or undirected; vertex s V
//Output: visit[u] is set to true for all nodes u reachable from v
for all u V :
visit[u] = false
visit[s] = true
Stack S = [s] (queue containing just s)
while S is not empty:
u = pop(S)
previsit(u)
for all edges (u,v) E:
if visit [v] = false:
push(S,v)
visit[v] = true;
postvisit(u)
DFS vs BFS
DFS goes depth first
Trying to go further if possible
Backtrack only when no other possible way to go
Using Stack
BFS goes breadth first
Trying to visit node by the distance from the
starting node
Using Queue
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 u V :
dist[u] = +
prev(u) = nil
dist[s] = 0
H = makequeue(V) (using dist-values as keys)
while H is not empty:
u = deletemin(H)
for all edges (u; v) E:
if dist[v] > dist[u] + l(u, v):
dist[v] = dist[u] + l(u, v)
prev[v] = u
decreasekey(H, 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,z) E:
if dist[z] > dist[v] + l(v,z):
dist[z] = dist[v] + l(v,z)
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
now, a shortest path must has at most |V| - 1
edges
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)
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)