250 likes | 379 Views
Nattee Niparnan. Graph Algorithm: Breadth First Search. Distance of nodes. The distance between two nodes is the length of the shortest path between them. S A 1. S C 1. S B 2. DFS and Length. DFS finds all nodes reachable from the starting node
E N D
NatteeNiparnan 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’sAlgo 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’sAlgo #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 • 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) Might be V2 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(Vlg 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)