פתרון

advertisement
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬
Practical Session #7 – Graph Algorithms.
BFS, DFS, Topological Sort
Graphs and BFS, DFS, Topological Sort
Graph
G = (V, E)
V(G) = V - Set of all vertices in G
E(G) = E - Set of all edges (u,v) in G, where u,v in V(G)

Adjacency Matrix: Dimensions V  V
M[i,j] = 1 - (vi, vj) in E(G)
M[i,j] = 0 - (vi, vj) not in E(G)
Adjacency List:
Each vertex v in V(G) has a list of all vertices u in V(G) where
(v,u) in E(G)
Graph
Representations

BFS(G, s)
Breadth-First Search
(V  G   v1
vn )
Starting from the source node s, BFS computes the minimal distance
from s to any other node v that can be reached from s. The algorithm
builds a breadth-tree rooted at s with the minimal paths to nodes that
can be reached from s.
The algorithm is suitable for directed or undirected graphs.



color[v] - the color of node v
o white - an unvisited node. The first time it is
encountered during the search it becomes nonwhite.
o gray - a visited node which has white neighbors
(draws a frontier between the visited and unvisited
nodes)
o black - a node whose neighbors were visited (colored
gray or black)
pred[v] - the predecessor of v in the breadth-tree
d[v] - the minimal distance from s to v
Time complexity: O(|V| + |E|)
DFS(G)
Depth-First Search
 Strategy: search "deeper" in the graph whenever possible.
 Edges are explored out of the most recently discovered vertex v
that still has unexplored edges leaving it. When all of v's edges
have been explored, the search "backtracks" to explore edges
leaving the vertex from which v was discovered. This process
continues until we have discovered all the vertices that are
reachable from the original source vertex.
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬






If any undiscovered vertices remain, then one of them is
selected as a new source and the search is repeated from that
source. This entire process is repeated until all vertices are
discovered.
The DFS may result in several trees, depending on the order of
choosing the first vertex in the set of unvisited vertices.
color[v] - the color of node v
o white - an unvisited node
o gray - a visited node
o black - a node whose adjacency list has been examined
completely (whose descendants were all searched).
pred[v] - the predecessor of v in the one of the depth trees
d[v] - the time when v was discovered
f[v] - the time when v was colored in black
A node v is white before d[v], gray between d[v] and f[v] and black
after f[v].
Time complexity: O(|V| + |E|)
TopologicalSort
Ordering of vertices in a directed acyclic graph (DAG) G=(V,E) such
that if there is a path from v to u in G, then v appears before u in the
ordering.
There could be many solutions, for example:
call DFS to compute f[v]
As the visit in each vertex is finished (blackened), insert it into the
front of a linked list
3. Return the linked list of the vertices
1.
2.
Time Complexity: O(|V|+|E|)
DFS can be used to classify the edges of the input graph G=(V,E).




Tree-edges
(u,v) - if v was initially discovered using edge from u to v
Back-edges
(u,v) - if v is an ancestor of u in the depth-tree
Forward-edges
(u,v) - not a tree-edge, where u is v's ancestor
Cross-edges
(u,v) - All the other edges, where u and v are vertices in
different depth-tree, u is not v's ancestor or v is not u's ancestor
It can be shown that if the graph is undirected then all of its edges are
tree edges or back edges. Therefore we define Forward-edges and
Cross-edges only in directed graphs
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬
Question 1
Given an undirected graph G = (V,E). For every 2 sets of vertices V1 and V2 such as:
V1  V2  V lets define:
the length of the shortest path from u to v in G.
the shortest path between a vextex v1 in V1 and v2 in V2.
distance(V1, V2) (Note: If V ∩ V ≠  then distance(V , V ) = 0).
1
2
1
2
distance(u,v)
Find distance(V1, V2) in O(|V| + |E|) time.
Solution:




Add 2 new vertices s and t to V(G).
E(G) = E(G)  { (s,u) : u V1 }  { (v,t) : v V2 }
Execute BFS from s and find d(t).
distance(V1,V2) = d(t)-2
Question 2
Update the BFS algorithm so that each node v in the graph will contain not only d[v], the length
of shortest path from s to v, but also the number of different paths of that length.
Solution:
Each node u in the graph will contain an extra field:
M(u) - the number of different paths to u of length d(u).


initialize M(v)0 for all the vertices except s. initialize M(s)1.
For each vertex u, when going over the neighbors v of u :
 if v is a white neighbor then
M(v)  M(u)
 else if d(v) = d(u)+1
// if v is not a white neighbor of u
M(v)  M(v) + M(u)
Question 3
Given an undirected graph G=(V,E) with a weight function w : E 
1, 2 on the edges.
a. Suggest an O(V+E) time algorithm to find the weight of the lightest path (i.e. the path for
which the sum of edge weights is minimal) from a given vertex s in V to another vertex t in
V.
b. How can you adjust you algorithm so that it will also print that path?
Solution:
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬
a. We use reduction. We turn G=(V,E) into an unweighted undirected graph G  V,E such
that we can use BFS to solve the problem.
Building G from G
 Init E  to E and V to V
 For each edge (u,v) of weight 2 in E
o Add a new vertex uv to V
o Remove (u,v) from E 
o add the edges (u,uv) and (uv,v) to E 
s
ab
s
1
a
2
a
b
1
c
2
1
t
d
b
c
t
cb
Clearly if there is a path of weight w in G then there is a path of length w in G (we simply have
to replace moving over every edge (u,v) of weight 2 in G for moving over the edges (u,uv) and
(uv,u) in G ).
In the same way if there exists a path of length w in G between 2 vertexes s, t  V then there
exists a path of weight w in G between those vertexes.
This means running BFS from s on the graph G will give us the length of the weight of all the
lightest paths in G that begin with s.
Runtime complexity:
The runtime complexity is O  V  E .
The algorithm runs in
T  n   c  V  E   c  V  E  E  E   3c  V  E   O  V  E 
b. In order to print the path in G when running BFS on G we need to be able to differentiate
between nodes in V that are from V and other nodes added to V in the for loop. We do this by
adding a new field “original” to each vertex in V , and correct the building algorithm
accordingly.
Building G from G
 Init E  to E and V to V
 For each v  V
o Set v.original to 1
 For each edge (u,v) of weight 2 in E
o Add a new vertex uv to V
o Set v.original to 0
o Remove (u,v) from E 
o add the edges (u,uv) and (uv,v) to E 
Now we can use the BFS on G to print and print only the vertexes belong to V.
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬
PrintShortestPath( G ,s,t)
 if s = t
o print s
o return
 PrintShortestPath( G ,s,pred[t])
 if t.original = 1
o print t
 return
Runtime complexity:
The runtime complexity is the length of the path in G . Note that the length of any simple path p
in G is at most |V|. The length of the corresponding path p  in G is at most double. Therefore
the printing algorithm runs in time.
T  n   c  2 V   2c V  O  V 
Question 4
Suggest algorithm in time O(|V|), independent of E, that determines whether a given undirected
graph contains a cycle.
Solution:
Lemma: An undirected graph is acyclic if and only if a DFS yields no back edges.
Back edge (u,v) is such that v has already been discovered and is u's ancestor.
(u,v) - if v is an ancestor of u in the depth-tree and (v,u) is not a tree-edge.
The DFS algorithm can be modified to classify edges as it
encounters them. In a depth-first search of an undirected
graph G, every edge of G is either a tree edge or a back
edge. if we arrive to a grey vertex (which means we
arrived there through back edge) we return to a vertex we
already visited and therefore the graph is cyclic.
v
tree edges
back edge
w
u
Asyclic(G=(V,E))
execute DFS on the graph while:
1. counting the number of visited nodes
2. if DFS visits a gray node return "cycle"
The algorithm runs in O(|V|) times, because in the worst case, when the graph is cyclic, the
algorithm reach a grey node (back edge) after it went through all the of the vertexes.
Question 5
A road from city A to city B is represented as a couple (A,B).
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬
Assume the roads are bi-directional.
Given a set of m roads and a set of n cities, suggest a way to preprocess the input in
O(n+m) time in order to support the following operation in O(1) time:
reachable(i,j) – Returns TRUE if it is possible to drive from city i to city j and FALSE otherwise.
Solution:
Preprocessing:
 Represent the input as an undirected graph G=(V,E), where the nodes represent the
cities and the edges represent the roads. The graph represented as an array A of size n,
each entry A[i] is the head of a linked list representing the neighbors of node i:
O(n+m)

Execute DFS and for each node i update a variable c[i], the connected-component to
whom it belongs: O(n+m)
Reachable(i,j): return TRUE if both i and j belong to the same connected-comp
Question 6
2 lists are given:
A - courses list. Every student must study all the courses in A.
B – Prerequisites. B contains tuples (a, b) (where a and b are in A), indicating that course a must
be taken before course b. The prerequisites dependencies are acyclic.
Design a schedule for each of the following students.
1. A lazy student who wants to take only one course in a semester.
2. A student who wants to take all the courses in A in the minimal number of semesters. The
student is willing to take any number of courses in a semester.
Example:
A = { Alg, Eng, Ds1, Ds2, Mat, Ph1, Ph2 }
B = { (Alg, Ds2), (Ds1, Ds2), (Mat, Ds1), (Ph1, Ph2) }
Optional output for student no. 1:
Optional output for student no. 2:
Semester 1: Eng
Semester 1: Eng, Mat, Ph1, Alg
Semester 2: Mat
Semester 2: Ds1, Ph2
Semester 3: Alg
Semester 3: Ds2
Semester 4: Ds1
Semester 5: Ds2
Semester 6: Ph1
Semester 7: Ph2
Solution:
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬
Assume that the courses names are integers in the range [1..n], n is known (n is not constant). The
relations between the courses will be represented by a directed graph G = (V, E), where V are the
set of courses and if course i is a prerequisite of course j, E will contain the edge (i, j). The graph
will be represented as an adjacency list.
The graph for the given example is:
Algorithm for a lazy student: Print the courses in a way that course i won't be printed before
course j, if j is prerequisite of i. In other words topologically sort the courses.
Complexity: O(|V| + |E|)
Now, let's observe another algorithm for topological sort of a DAG in O(|V|+|E|).


Find in-degree of all the vertices and keep a list of vertices with
in-degree=0
- O(|V|+|E|)
Repeat:
Extract a vertex v with in-degree of 0 from the list - O(1)
o output v and remove it from G, along with its edges,
o reduce the in-degree of each node u such as (v,u) was an edge in G and add to the list
vertices with in-degree=0, if necessary - O(d(v))
o repeat the process until all the vertices were removed
Algorithm for a hard working student: A variation of the above topological sort algorithm
with a slight change. In each semester k, execute the algorithm on all the nodes with degree 0
simultaneously (instead of dealing with one source at each stage, all the sources will be dealt and
printed in one semester.)
(note that the topological sort is not necessary because after we find the vertexes with in-degree
0, we can go to the next vertexes through the edges.)
Complexity: O(|V| + |E|)
Question 7
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬
Given a DAG (directed acyclic graph) G = (V,E) with weighted edges. Suggest an O(|V|+|E|)
time algorithm for finding the weight of the maximum weight path in G.
Solution:
1. First, for every vertex v, create a list of all in-edges, i.e., list of all the vertices u, such that (u,v)
 E, that takes O(V+E)
2. Define a new array A for which A[i] = the maximal weighted path that ends in vi.
3. By definition, A[i] = max{A[j]+w(j,i) : (j,i) E }.
4. Start by computing A[i] for all i = 1..n, where v1, v2, …, vn is the topological ordering. Since
the graph was topologically sorted, when computing A[i], all the values A[j] of it’s neighbors j
was already computed (all i's neighbors appear before it in the topological ordering).
5. After computing A[i] for all the nodes, find vk for which A[k] is maximal.
MaxPath( DAG G)
for i ← 1 to n do:
Create-in-edges-list(i)
v1, v2, …, vn ← TopologicalSort(G)
A ← new array [1..n]
A[1] ← 0
for i ← 2 to n do:
A[i] ← max{A[j]+w(j,i) : (j,i)  E }
return max{A[1],A[2],…,A[n]}
We design the algorithm
1. Express the solution to a problem in terms of solutions to smaller problems.
2. Solve all the smallest problems first and put their solutions in a table
3. Solve the next larger problems, and so on, up to the problem one originally wanted to solve.
4. Each problem should be easily solvable by looking up and combining solutions of smaller
problems in the table.
Time Complexity:
Topological sort - O(|V|+|E|)
Updating A - O(|E|) find maximal value in A O(|V|)
Total: O(|V|+|E|)
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬
MST Algorithms: Kruskal and Prim
Kruskal
The algorithm starts with |V| different trees (each tree consisting of one of the
vertices in V) and each time unions the trees by adding the next minimal weight edge
that doesn't creates a cycle.
Prim
The algorithm starts in the tree T={r} (tree consisting of a single vertex) and extends
it until it spans all the vertices in V(G).
In each iteration the minimal weight edge of all the edges connecting T to the
vertices that have not been covered by T yet is added to T.
key[u] =min{w(u,v): (u,v)E(G) and vT}
MST-Prim (G, w, r)
Q ← V(G)
for each v  Q
key[v] ← ∞
key[r] ← 0
π[r] ← NIL
while Q ≠ Ø
v ← Extract-Min(Q)
for each u  Adj[v]
if u  Q and w(v,u) < key[v]
π[u] ← v
key[u] ← w(v,u)
Update (Q, u)
Complexity:
O(VlogV + ElogV) if using binary heap
Question 8:
Without changing Prim's algorithm, give an algorithm for computing the maximum-weight
spanning tree in a graph and analyze its complexity.
Solution:
Given a graph G=(V,E) and w – weight function, construct a new graph with same nodes and
edges, with new weight function w': w'(u,v) = -w(u,v).
Minimum spanning tree in this new graph is maximum weight spanning tree in the
original one.
‫מבני נתונים ‪ -‬סמסטר ג' תש"ע‬
‫‪Example:‬‬
‫שאלה ‪9‬‬
‫יש לתכנן רשת תקשורת עבור ‪ n‬ערים‪ ,‬כאשר מחיר הנחת קו בין עיר ‪ u‬ועיר ‪ v‬הוא המרחק בין שתי הערים (בקו‬
‫אווירי)‪ .‬יש לתכנן רשת תקשורת כך שמחיר הנחתה יהיה מינימאלי תוך התחשבות בתנאים הבאים‪:‬‬
‫* חלק מהערים כבר מחוברות ביניהן ע"י קווי תקשורת ולכן ניתן לחסוך בהקמת הרשת החדשה ע"י שימוש בתשתיות‬
‫קיימות‪.‬‬
‫* בחלק מן הערים (שאינן מחוברות לתשתיות קיימות) קמו ארגוני ירוקים שמתנגדים לחיבור קווי תקשורת ואנחנו‬
‫מעוניינים לחבר את אותן ערים למספר קטן ככל האפשר של קווי תקשורת‪ ,‬כלומר למזער את מספרם של קווי‬
‫התקשורת ברשת אשר מחוברים לאיזושהי עיר "ירוקה"‪.‬‬
‫הצע אלגוריתם למציאת רשת בעלות מינימאלית‪.‬‬
‫פתרון‪:‬‬
‫רדוקציה לבעיית ‪:MST‬‬
‫נייצג את הערים וקווי התקשורת ע"י גרף ‪ G  V , E‬כאשר נעניק לכל זוג ערים משקל עבור הצלע שמחברת אותם‬
‫באופן הבא‪:‬‬
‫כל קווי התקשורת הקיימים יקבלו משקל ‪. 0‬‬
‫כל קווי התקשורת האחרים אשר אינם מקושרים לעיר שבה יש ארגוני‪-‬ירוקים יקבלו את המשקל של עלות הקמתם‪.‬‬
‫לבסוף‪ ,‬נסמן ב‪ X-‬את המרחק המקסימאלי של שתי ערים כלשהן‪ .‬עבור קווי התקשורת שקשורות לעיר או ערים שבהן‬
‫יש ארגוני ירוקים‪ ,‬נעניק לצלע משקל שהוא המרחק בין שתי הערים ‪.X +‬‬
‫על הרשת שנוצרה נחשב ‪.MST‬‬
‫נבחן את התנהגותו של האלגוריתם של קרוסקל לחישוב ‪ MST‬על הגרף שהגדרנו‪.‬‬
‫בסדר המיון של הצלעות‪ ,‬יופיעו בהתחלה כל הצלעות שמייצגות קווי‪-‬תקשורת קיימים‪ ,‬אח"כ כאלו המייצגות קוי‪-‬‬
‫תקשורת לערים "לא‪-‬ירוקות" ולבסוף צלעות המייצגות קווי‪-‬תקשורת לערים "ירוקות"‪.‬‬
‫לכן‪ ,‬בהתחלה הוא יבחר קווי תקשורת קיימים והוא יעבור לבחור צלעות שיש להן משקל גדול מ‪ 0-‬רק לאחר שימצה‬
‫את האפשרות לבחור צלעות במשקל ‪ .0‬לאחר מכן‪ ,‬יבחר מתוך הצלעות שמייצגות קוי‪-‬תקשרות של ערים "לא‪-‬ירוקות"‬
‫ויעבור לבחור קווים לערים ירוקות רק לאחר שימצה את האפשרות לצלעות אחרות‪.‬‬
‫מבני נתונים ‪ -‬סמסטר ג' תש"ע‬
‫שאלה ‪10‬‬
‫סאבקומנדנטה צריך למסור הודעה לכל ‪ N‬הפעילים בקבוצה ‪ ,‬ההודעה כמובן צריכה להשאר סודית‪.‬‬
‫לכל שני פעילים ‪ i, j‬הנמצאים בקשר יש הסתברות ידועה ‪ 0 < P(i,j) > 1‬שאם ‪ i‬מעביר את ההודעה ל‪ j-‬ההודעה‬
‫תתגלה‪ .‬המטרה של סאבקומדנטה היא לתכנן את רשת העברת ההודעה כך המידע יגיע לכל הפעילים תוך מזעור‬
‫הסתברות גלוי ההודעה‪ .‬מה יעשה ?‬
‫פתרון‪:‬‬
‫נבנה גרף על כל הפעילים‪ ,‬כאשר יש צלע בין כל שני פעילים הנמצאים בקשר‪.‬‬
‫אנחנו רוצים שההודעה תגיע לכל הפעילים ולכן מחפשים תת‪-‬גרף בו יש מסלול מסאבקומנדנטה לכל הפעילים‪ ,‬כלומר‪,‬‬
‫תת‪-‬גרף קשיר‪.‬‬
‫בתת‪-‬גרף האופטימאלי עבורנו לא יופיע מעגל‪ ,‬מכיוון שלו היה מעגל היה ניתן לזרוק צלע במעגל בלי לפגוע בקשירות‬
‫ותוך הפחתת הסיכון להתגלות‪ ,‬ולפיכך לא היה אופטימאלי‪.‬‬
‫ולכן אנחנו מחפשים תת‪-‬עץ של הגרף עבורו ההסתברות לגילוי ההודעה מינימאלי‪.‬‬
‫ההסתברות לאי גילוי ההודעה עבור צלע בודדת הוא ((‪ )1-P(i,j‬ולכן ההסתברות הכללית לגילוי ההודעה עבור תת‪-‬עץ‬
‫כלשהוא ‪ T‬הוא‪  (1  P(i, j )) :‬על פני כל ‪(i, j )  T‬‬
‫‪j )T‬‬
‫עבורו‪  (1  P(i, j ))(i ,‬על פני כל ‪ (i, j )  T‬הוא מקסימלי‪.‬‬
‫כלומר אנחנו מחפשים עץ ‪T‬‬
‫עולה) ‪( i , j‬‬
‫‪T‬‬
‫ולכן מחפשים ‪ T‬כך ש { )) ‪ log{  (1  P(i, j‬מקסימלי‪.‬‬
‫נשתמש בכך ש ()‪ log‬היא פונקציה מונוטונית‬
‫‪( i , j )T‬‬
‫אבל‪log{  (1  P(i, j )) { =  log( 1  P (i, j ) :‬‬
‫ולכן שקול למציאת עץ ‪( i , j )T‬‬
‫שלנו) ‪( i , j‬‬
‫‪T‬‬
‫כאשר משקל צלע )‪ (i,j‬הוא ))‪log(1-P(i,j‬‬
‫פורש מקסימלי בגרף‬
‫או לחלופין למציאת ‪ MST‬כאשר משקל צלע )‪ (i,j‬הוא ()‪ -log(1-P(i,j) ( -log(1-P(i,j‬הוא מספר חיובי) ‪.‬‬
‫שאלה ‪11‬‬
‫האם אפשר לפתור הבעיה הקודמת ללא הפונקציה )(‪? log‬‬
‫פתרון‪:‬‬
‫למעשה אפשר להריץ ‪ MST‬כאשר משקל צלע )‪ (i,j‬הוא (‪!! P(i,j‬‬
‫בריצת ‪ prim‬על הגרף תחת כל אחת משני המישקולים השונים אותה הצלע תבחר בכל שלב !‬
‫כאשר (‪ P(i,j‬מינימלי בכל שלב אמ"ם ))‪ -log(1-P(i,j‬מינימלי‪.‬‬
‫(כלומר הפתרון הקודם רק מסביר למה זה עובד )‪.‬‬
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬
Dijkstra Algorithm
Example of Dijkstra Algorithm Execution
Execute the Dijkstra algorithm on the following graph, with single-source s.
Execution:
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬
Why Any Single-Source Shortest Path Algorithm Does Not Allow Negative-Weighted
Circles?
Consider a path from S to v that contains a circle with a negative total weight. No path from S to
v is can be a shortest path – a lesser-weight path can always be found that follows the proposed
"shortest path" and then traverses the negative-weight cycle. That is,  ( S , v)   .
Why Doesn't Dijkstra Work on Graphs With Negative Weights?
The following figure presents a simple example where Dijkstra's algorithm would find an
incorrect shortest path if negative-weight edges were allowed:
In this example, the algorithm finds that the shortest path from s to c is <s,c> , weighted 3, and
then insert c to S, where it should not change anymore, while the actual shortest path from s to
c is <s,b,c>, weighted 1.
Question 11
The following is an algorithm for finding single source shortest-paths for a graph G with possibly
negative weighted edges.
1. Find the minimal weight in G, Wmin
2. To each weight in G, add |Wmin|
3. Execute Dijkstra's algorithm
Does this algorithm indeed find shortest paths?
Solution:
The algorithm doesn’t work correctly: it adds more weight to the paths with more edges.
Consider the following example:
‫ סמסטר ג' תש"ע‬- ‫מבני נתונים‬
The upper path is the shortest.
Wmin = -2, | Wmin|=2. Add 2 to each path
The algorithm will find that the lower path is the shortest, which contradicts the
assumption that the algorithm computes shortest paths.
Question 11
Given a directed graph G = (V, E), where each edge (u,v)  E has a value r,
0 ≤ r(u,v) ≤1, that indicates the reliability of a communication channel, that is, the probability
that a message sent from u is received at v.
Suggest an algorithm for finding the most reliable channel between two given vertices s and t.
Solution:
The most reliable channel from vertex s to vertex t is the channel with the highest probability of
being in order, meaning the channel: s→v1→v2→...→vk→t
where r(s, v1)r(v1, v2)...r(vk, t) is maximal (independent probabilities).
The modifications in Dijkstra's algorithm are as follows:
1.
2.
3.
4.
Change Extract-Min(Q), to Extract-Max(Q)
Change '+' to '*'
Initialize d[s] with 1 (identity for *) instead of with 0 (identity for +)
Initialize d[v] with -∞ (identity for max) instead of with ∞ (identity for min)
‫מבני נתונים ‪ -‬סמסטר ג' תש"ע‬
‫)‪Dijkstra(G, w, s‬‬
‫)‪Initialize-Single-Source(G, s‬‬
‫‪S←‬‬
‫]‪Q ← V[G‬‬
‫‪while Q ≠  do‬‬
‫)‪u ← Extract-Max(Q‬‬
‫}‪S ← S  {u‬‬
‫‪for each vertex v  Adj[u] do‬‬
‫)‪Relax(u, v‬‬
‫)‪Initialize-Single-Source(G, s‬‬
‫)‪for each vertex v  V(G‬‬
‫∞‪d[v] ← -‬‬
‫‪π[v] ← NIL‬‬
‫‪d[s] ← 1‬‬
‫)‪Relax(u, v‬‬
‫)‪if d[v] < d[u]*w(u,v‬‬
‫)‪d[v] ← d[u]*w(u,v‬‬
‫‪π[v] ← u‬‬
‫)‪Update(Q, v‬‬
‫שאלה ‪( 11‬העשרה‪ ,‬שאלה קשה)‪:‬‬
‫‪ ‬נתון גרף מכוון ‪ G  V , E ‬ופונקצית משקל על הצלעות ‪( w : E  R ‬משקלות חיוביים)‪ ,‬כאשר‬
‫הקודקודים ‪ V‬מתארים צמתים ברשת כבישים והצלעות ‪ E‬מתארות את כבישים (אורך הכביש הוא משקל‬
‫הצלע)‪.‬‬
‫‪ ‬תת‪-‬קבוצת קודקודים ‪ S  V‬שמסמלת את קבוצת הצמתים המרומזרים‪.‬‬
‫‪ ‬קודקוד התחלה ‪ s V \ S‬וקודקוד סיום ‪( t V \ S‬הצמתים המתאימים אינם מרומזרים)‪.‬‬
‫צריך למצוא‪ :‬מסלול קצר ביותר מ‪ s -‬ל‪ t -‬העובר בלכל היותר שני קודקודים מ‪. S -‬‬
‫פתרון‪:‬‬
‫מהגרף ‪ G  V , E ‬נבנה גרף חדש באופן הבא‪:‬‬
‫‪‬‬
‫עבור כל קודקוד בגרף המקורי ‪ , x V‬ניצור שלושה קדקודים בגרף החדש ‪ , x0 , x1 , x2‬כאשר המשמעות היא‬
‫שאם הגענו ל‪ xi -‬מ‪ , s -‬אזי עברנו בדרך ב‪ i -‬רמזורים‪ .‬ניתן לדמיין את הגרף החדש כשכפול של הגרף‬
‫המקורי לשלוש שכבות‪ ,‬כאשר כל שכבה מייצגת את מספר הרמזורים שנתקלנו בהם עד עתה‪ .‬כמו כן‪ ,‬נוסיף‬
‫עוד קדקוד `‪ ,t‬אשר יהיה קודקוד היעד במופע שניצור‪ .‬נגדיר‪,‬‬
‫‪V '  xi : i  0,1, 2; x V   t '‬‬
‫מבני נתונים ‪ -‬סמסטר ג' תש"ע‬
‫‪‬‬
‫קבוצת הצלעות ‪ E '  E1  E2  E3‬תורכב מצלעות בתוך כל שכבה ‪ , E1‬צלעות בין שכבות ‪ , E2‬וצלעות‬
‫נוספות ‪ , E3‬כפי שמוסבר‪.‬‬
‫‪ .1‬צלעות בתוך כל שכבה ( ‪:) E1‬‬
‫‪E1  ( xi , yi ) | ( x, y)  E, y  S , i {0,1, 2}‬‬
‫קבוצת הצלעות הראשונה ‪ E1‬מורכבת מהצלעות בתוך כל שכבה שמקבילות לכל הצלעות בגרף המקורי‬
‫‪ , e  ( x, y )  E‬כך ש‪ y -‬אינו צומת מרומזר ( ‪.) y  S‬משקלן של צלעות האלו יהיה כמשקל הצלע‬
‫המתאימה בגרף המקורי ) ‪. w '( xi , yi )  w( x, y‬‬
‫‪ .2‬צלעות בין שכבות ( ‪:) E2‬‬
‫‪E2  ( xi , yi 1 ) : ( x, y)  E; y  S , i {0,1}‬‬
‫קבוצת הצלעות השנייה ‪ E2‬מורכבת מהצלעות משכבה ‪ 0‬ל‪ 1 -‬ומהצלעות משכבה ‪ 1‬ל‪. 2 -‬‬
‫צלעות אלה מקבילות לכל הצלעות בגרף המקורי ‪ , e  ( x, y )  E‬כך ש‪ y -‬הוא צומת‬
‫מרומזר ( ‪ .) y  S‬משקלן של צלעות האלו יהיה כמשקל הצלע המתאימה בגרף המקורי‬
‫)‪. w '( xi , yi 1 )  w( x, y‬‬
‫‪ .3‬צלעות נוספות ( ‪:) E3‬‬
‫‪E3  (t0 , t '),(t1 , t '),(t2 , t ')‬‬
‫קבוצת הצלעות השלישית ‪ E3‬מורכבת מצלעות עם משקל ‪ 0‬שמאפשרות להגיע מ‪ ti -‬ל‪ t -‬ללא עלות‪ ,‬זאת‬
‫כיוון שאנו מקבלים מצב שבו חצינו לכל היותר ‪ 2‬רמזורים‪ .‬משקלן של צלעות האלו הוא ‪. w '(ti , t ')  0‬‬
‫אחרי בניית הגרף החדש‪:‬‬
‫נריץ את האלגוריתם של ‪ Dijkstra‬על בגרף החדש שיצרנו ונמצא מסלול זול ביותר מהמקור ‪ s0‬ליעד ' ‪. t‬‬
‫אחרי הרצת אלג' ‪ Dijkstra‬על הגרף החדש נקבל מסלול ‪ P'  s0  x 0 , x1 ,..., x k  t '‬ב‪ G ' -‬בעל מחיר ‪ ,L‬את‬
‫המסלול הנ"ל נוכל להמיר למסלול זול ביותר מ‪ s-‬ל‪ t-‬ב‪ G-‬העובר בלכל היותר שני צמתים מרומזרים‪ .‬המסלול שנקבל‬
‫יהיה אף הוא בעלות ‪. L‬‬
‫‪‬‬
‫כיוון שהצלעות היחידות שמובילות ל‪ t ' -‬הן מ‪ , E3 -‬לכן ‪ , x k 1  ti‬עבור }‪ i  {0,1, 2‬כלשהו‪ .‬כיוון‬
‫‪‬‬
‫נשארנו עם מסלול המכיל צלעות ‪ E1‬ו‪ E2 -‬בלבד‪ .‬כאשר יש בדיוק ‪ i‬צלעות מ‪( E2 -‬עברנו בלכל היותר‬
‫‪ i‬רמזורים ולכן עברנו לכל היותר ‪ i‬פעמים בין שכבות)‪.‬‬
‫‪j‬‬
‫‪j 1‬‬
‫יהי ‪ P  s  y 0 , y1 ,..., y k 1  t‬מסלול ב‪ G -‬כאשר צלע ‪ ( y , y )  E‬מתאימה ל‪-‬‬
‫‪ ( x j , x j 1 )  E1‬אם ‪( y j 1  S‬צומת מרומזר) או ל‪ ( x j , x j 1 )  E2 -‬אם ‪( y j 1  S‬צומת מרומזר)‪,‬‬
‫עבור }‪. j  {0,1, , k  2‬‬
‫עלות המסלול ‪ P‬היא גם ‪ L‬לפי הגדרת משקל הצלעות‪.‬‬
‫‪‬‬
‫‪‬‬
‫שמשקל צלעות אלה ב‪ G ' -‬הוא ‪ , 0‬נסיק כי עלות המסלול ‪  x 0 , x1 ,..., x k 1‬היא ‪. L‬‬
‫‪‬‬
‫‪‬‬
‫זמן ריצה‬
‫‪‬‬
‫יצירת הגרף `‪:G‬‬
‫‪ o‬מס' הקדקודים הוא ‪ , 3V  1‬וניתן ליצור אותם ב‪. OV -‬‬
‫‪ o‬מס' הצלעות הוא לכל היותר ‪ , 3 E  3‬וניתן ליצור אותם ב‪. O E  -‬‬
‫מבני נתונים ‪ -‬סמסטר ג' תש"ע‬
‫‪ o‬יצירת פונקצית המשקל `‪ w‬מלווה את יצירת הצלעות ולוקחת ‪. O E ‬‬
‫‪‬‬
‫‪‬‬
‫הרצת האלגוריתם של ‪ Dijkstra‬דורשת ‪. O E'  V ' log V ' ‬‬
‫שימו לב‪ :‬הזמן הוא במונחי המופע החדש שיצרנו וצריך לעבור למונחי המופע המקורי‪.‬‬
‫מכיוון שבגרף שיצרנו יש ‪ 3V  1‬קודקודים ולכל היותר ‪ 3 E  3‬צלעות‪ ,‬נקבל ‪. O E  V log V ‬‬
‫המרת המסלול שקיבלנו למסלול בגרף המקורי תארך כאורכו של המסלול ‪. OV ‬‬
‫ולכן זמן הריצה כולו הוא ‪. O E  V log V ‬‬
Download