Discrete Mathematics β Walkthrough Track Β· real-life examples, full execution traces, good & bad cases
Notes By Pr. El Hadiq Zouhair
1 / 14Eight core algorithms, each presented the same way so you really understand what happens inside:
Algorithms covered: BFS Β· DFS Β· Topological sort Β· Bipartite check Β· Dijkstra Β· BellmanβFord Β· Minimum Spanning Tree (Kruskal & Prim) Β· Greedy colouring.
Idea. Explore layer by layer from the source using a FIFO queue. The first time a vertex is reached, the number of edges used is its shortest (hop) distance β so it is final immediately.
Example graph. Friendships: AnaβBilal, AnaβCarla, BilalβDiego, CarlaβDiego, CarlaβEva, DiegoβFarah. We run bfs(G, "Ana") and watch the queue and dist at every dequeue:
| Step | Dequeue u | Discovered (v:dist) | Queue after | dist |
|---|---|---|---|---|
| 0 | β (init) | β | [Ana] | {Ana:0} |
| 1 | Ana | Bilal:1, Carla:1 | [Bilal, Carla] | {Ana:0, Bilal:1, Carla:1} |
| 2 | Bilal | Diego:2 | [Carla, Diego] | {Ana:0, Bilal:1, Carla:1, Diego:2} |
| 3 | Carla | Eva:2 | [Diego, Eva] | {Ana:0, Bilal:1, Carla:1, Diego:2, Eva:2} |
| 4 | Diego | Farah:3 | [Eva, Farah] | {Ana:0, Bilal:1, Carla:1, Diego:2, Eva:2, Farah:3} |
| 5 | Eva | β | [Farah] | {Ana:0, Bilal:1, Carla:1, Diego:2, Eva:2, Farah:3} |
| 6 | Farah | β | [] | {Ana:0, Bilal:1, Carla:1, Diego:2, Eva:2, Farah:3} |
| Path | BFS sees | Real cost |
|---|---|---|
| AβC direct | 1 hop | 20 (expensive) |
| AβBβC | 2 hops | 5 + 6 = 11 (cheaper) |
Idea. Dive deep before backtracking. Iteratively this uses an explicit stack (LIFO); recursively it uses the function call stack. Great for reachability, connected components and cycle detection.
Iterative trace on the maze aβb, aβc, bβd, cβd, dβe (the explicit stack):
| Step | Action | Pushed | Stack after | Visited |
|---|---|---|---|---|
| 0 | β (init) | β | [a] | {} |
| 1 | pop a | push [b, c] | [b, c] | [a] |
| 2 | pop c | push [d] | [b, d] | [a, c] |
| 3 | pop d | push [b, e] | [b, b, e] | [a, c, d] |
| 4 | pop e | β | [b, b] | [a, c, d, e] |
| 5 | pop b | β | [b] | [a, b, c, d, e] |
| 6 | pop b | already seen β skip | [] | [a, b, c, d, e] |
Recursive trace on the same graph β watch the call stack grow on enter and unwind on finish (a primed step number marks the backtrack):
| Step | Event | Call stack | Visited |
|---|---|---|---|
| 1 | enter a | β [a] | [a] |
| 2 | enter b | β [a, b] | [a, b] |
| 3 | enter d | β [a, b, d] | [a, b, d] |
| 4 | enter c | β [a, b, d, c] | [a, b, c, d] |
| 4β² | finish c | β [a, b, d, c] | [a, b, c, d] |
| 5 | enter e | β [a, b, d, e] | [a, b, c, d, e] |
| 5β² | finish e | β [a, b, d, e] | [a, b, c, d, e] |
| 5β² | finish d | β [a, b, d] | [a, b, c, d, e] |
| 5β² | finish b | β [a, b] | [a, b, c, d, e] |
| 5β² | finish a | β [a] | [a, b, c, d, e] |
The prerequisite graph:
Step 0 β initial in-degree (how many prerequisites each course still has):
| Course | In-degree | Prerequisites |
|---|---|---|
| PL | 0 | β (none) |
| LE | 1 | PL |
| PR | 1 | LE |
| RI | 1 | PR |
| ST | 1 | PR |
| OS | 1 | ST |
| RF | 1 | OS |
| SS | 1 | RF |
| PT | 1 | RI |
| MI | 1 | PT |
| CO | 1 | ST |
| BI | 1 | CO |
| GR | 2 | RF, MI |
Every iteration: dequeue an unlocked course, decrement its successors' in-degrees, enqueue any that just hit 0.
| Step | Dequeue | Neighbours' in-degree β1 | Newly 0 (enqueue) | Queue after | Order so far |
|---|---|---|---|---|---|
| 0 | β (init) | β | β | [PL] | [] |
| 1 | PL | LE:0 | [LE] | [LE] | [PL] |
| 2 | LE | PR:0 | [PR] | [PR] | [PL, LE] |
| 3 | PR | RI:0, ST:0 | [RI, ST] | [RI, ST] | [PL, LE, PR] |
| 4 | RI | PT:0 | [PT] | [ST, PT] | [PL, LE, PR, RI] |
| 5 | ST | OS:0, CO:0 | [OS, CO] | [PT, OS, CO] | [PL, LE, PR, RI, ST] |
| 6 | PT | MI:0 | [MI] | [OS, CO, MI] | [PL, LE, PR, RI, ST, PT] |
| 7 | OS | RF:0 | [RF] | [CO, MI, RF] | [PL, LE, PR, RI, ST, PT, OS] |
| 8 | CO | BI:0 | [BI] | [MI, RF, BI] | [PL, LE, PR, RI, ST, PT, OS, CO] |
| 9 | MI | GR:1 | β | [RF, BI] | [PL, LE, PR, RI, ST, PT, OS, CO, MI] |
| 10 | RF | SS:0, GR:0 | [SS, GR] | [BI, SS, GR] | [PL, LE, PR, RI, ST, PT, OS, CO, MI, RF] |
| 11 | BI | β | β | [SS, GR] | [PL, LE, PR, RI, ST, PT, OS, CO, MI, RF, BI] |
| 12 | SS | β | β | [GR] | [PL, LE, PR, RI, ST, PT, OS, CO, MI, RF, BI, SS] |
| 13 | GR | β | β | [] | [PL, LE, PR, RI, ST, PT, OS, CO, MI, RF, BI, SS, GR] |
Resulting study plan: PL β LE β PR β RI β ST β PT β OS β CO β MI β RF β BI β SS β GR.
5 / 14The same ordering can be produced by DFS: a course is prepended to the plan only once all the courses it unlocks are finished. Watch the recursion enter and finish:
| Step | Event | Call stack | Order (prepend on finish) |
|---|---|---|---|
| 1 | enter PL | β [PL] | [] |
| 2 | enter LE | β [PL, LE] | [] |
| 3 | enter PR | β [PL, LE, PR] | [] |
| 4 | enter RI | β [PL, LE, PR, RI] | [] |
| 5 | enter PT | β [PL, LE, PR, RI, PT] | [] |
| 6 | enter MI | β [PL, LE, PR, RI, PT, MI] | [] |
| 7 | enter GR | β [PL, LE, PR, RI, PT, MI, GR] | [] |
| 7β² | finish GR β prepend | β [PL, LE, PR, RI, PT, MI, GR] | [GR] |
| 7β² | finish MI β prepend | β [PL, LE, PR, RI, PT, MI] | [MI, GR] |
| 7β² | finish PT β prepend | β [PL, LE, PR, RI, PT] | [PT, MI, GR] |
| 7β² | finish RI β prepend | β [PL, LE, PR, RI] | [RI, PT, MI, GR] |
| 8 | enter ST | β [PL, LE, PR, ST] | [RI, PT, MI, GR] |
| 9 | enter OS | β [PL, LE, PR, ST, OS] | [RI, PT, MI, GR] |
| 10 | enter RF | β [PL, LE, PR, ST, OS, RF] | [RI, PT, MI, GR] |
| 11 | enter SS | β [PL, LE, PR, ST, OS, RF, SS] | [RI, PT, MI, GR] |
| 11β² | finish SS β prepend | β [PL, LE, PR, ST, OS, RF, SS] | [SS, RI, PT, MI, GR] |
| 11β² | finish RF β prepend | β [PL, LE, PR, ST, OS, RF] | [RF, SS, RI, PT, MI, GR] |
| 11β² | finish OS β prepend | β [PL, LE, PR, ST, OS] | [OS, RF, SS, RI, PT, MI, GR] |
| 12 | enter CO | β [PL, LE, PR, ST, CO] | [OS, RF, SS, RI, PT, MI, GR] |
| 13 | enter BI | β [PL, LE, PR, ST, CO, BI] | [OS, RF, SS, RI, PT, MI, GR] |
| 13β² | finish BI β prepend | β [PL, LE, PR, ST, CO, BI] | [BI, OS, RF, SS, RI, PT, MI, GR] |
| 13β² | finish CO β prepend | β [PL, LE, PR, ST, CO] | [CO, BI, OS, RF, SS, RI, PT, MI, GR] |
| 13β² | finish ST β prepend | β [PL, LE, PR, ST] | [ST, CO, BI, OS, RF, SS, RI, PT, MI, GR] |
| 13β² | finish PR β prepend | β [PL, LE, PR] | [PR, ST, CO, BI, OS, RF, SS, RI, PT, MI, GR] |
| 13β² | finish LE β prepend | β [PL, LE] | [LE, PR, ST, CO, BI, OS, RF, SS, RI, PT, MI, GR] |
| 13β² | finish PL β prepend | β [PL] | [PL, LE, PR, ST, CO, BI, OS, RF, SS, RI, PT, MI, GR] |
| Step | Dequeue | note | Queue | Order |
|---|---|---|---|---|
| 0 | init | β | [D] | [] |
| 1 | D | β | [] | [D] |
| END | len(order)=1 β 4 | queue empty but B,C unprocessed | [] | [D] |
Idea. BFS-colour the graph alternately 0/1. If an edge ever joins two same-coloured vertices, an odd cycle exists and no 2-split is possible.
Good case β conflict graph 1β4,1β5,2β4,2β6,3β5,3β6 (an even structure). The colour map fills without clash:
| Step | Action | Assigned (v=color) | Queue | color map |
|---|---|---|---|---|
| 0 | seed 1=0 | β | [1] | {1:0} |
| 1 | pop 1 | 4=1, 5=1 | [4, 5] | {1:0, 4:1, 5:1} |
| 2 | pop 4 | 2=0 | [5, 2] | {1:0, 4:1, 5:1, 2:0} |
| 3 | pop 5 | 3=0 | [2, 3] | {1:0, 4:1, 5:1, 2:0, 3:0} |
| 4 | pop 2 | 6=1 | [3, 6] | {1:0, 4:1, 5:1, 2:0, 3:0, 6:1} |
| 5 | pop 3 | β | [6] | {1:0, 4:1, 5:1, 2:0, 3:0, 6:1} |
| 6 | pop 6 | β | [] | {1:0, 4:1, 5:1, 2:0, 3:0, 6:1} |
None:| Step | Action | Assigned (v=color) | Queue | color map |
|---|---|---|---|---|
| 0 | seed u=0 | β | [u] | {u:0} |
| 1 | pop u | v=1, w=1 | [v, w] | {u:0, v:1, w:1} |
| 2 | pop v | β | [w] | {u:0, v:1, w:1} β΅ CONFLICT w==v=1 |
Trace from S on a 6-junction city (weights = minutes). Each pop settles a vertex; relaxations update dist and push onto the heap:
| Step | Pop (dist,vertex) | Relaxations (v:oldβnew) | dist | heap after |
|---|---|---|---|---|
| 0 | β (init) | β | {S:0} | [(0, 'S')] |
| 1 | pop (0,S) βsettled | A:ββ7, B:ββ2 | {S:0, A:7, B:2} | [(2, 'B'), (7, 'A')] |
| 2 | pop (2,B) βsettled | A:7β5, C:ββ10, D:ββ7 | {S:0, A:5, B:2, C:10, D:7} | [(5, 'A'), (7, 'A'), (7, 'D'), (10, 'C')] |
| 3 | pop (5,A) βsettled | C:10β9 | {S:0, A:5, B:2, C:9, D:7} | [(7, 'A'), (7, 'D'), (9, 'C'), (10, 'C')] |
| 4 | pop (7,A) | stale β skip | {S:0, A:5, B:2, C:9, D:7} | [(7, 'D'), (9, 'C'), (10, 'C')] |
| 5 | pop (7,D) βsettled | E:ββ10 | {S:0, A:5, B:2, C:9, D:7, E:10} | [(9, 'C'), (10, 'C'), (10, 'E')] |
| 6 | pop (9,C) βsettled | β | {S:0, A:5, B:2, C:9, D:7, E:10} | [(10, 'C'), (10, 'E')] |
| 7 | pop (10,C) | stale β skip | {S:0, A:5, B:2, C:9, D:7, E:10} | [(10, 'E')] |
| 8 | pop (10,E) βsettled | β | {S:0, A:5, B:2, C:9, D:7, E:10} | [] |
| Step | Action | What happens | dist |
|---|---|---|---|
| 1 | pop (0,S) | relax A:0β2, B:0β5 | {S:0, A:2, B:5} |
| 2 | pop (2,A) βsettled | A has edge AβB = -4 β B:5β-2 | {S:0, A:2, B:-2} |
| β | but B was about to be settled at 5β¦ | Dijkstra already trusts A=2 as final | wrong if a later negative edge could lower it |
Idea. Relax every edge, repeated $|V|-1$ times. After that many passes all shortest distances are final; one more improving pass would reveal a negative cycle.
Trace from S with a negative edge AβC = β4 (no negative cycle). Watch dist stabilise pass by pass:
| Round | Relaxations this pass (v:oldβnew) | dist after pass |
|---|---|---|
| 0 (init) | β | {S:0, A:β, B:β, C:β, D:β} |
| pass 1 | A:ββ6, B:ββ7, C:ββ2, D:ββ11, D:11β4, B:7β4 | {S:0, A:6, B:4, C:2, D:4} |
| pass 2 | D:4β1 | {S:0, A:6, B:4, C:2, D:1} |
| pass 3 | (no change β stop early possible) | {S:0, A:6, B:4, C:2, D:1} |
| pass 4 | (no change β stop early possible) | {S:0, A:6, B:4, C:2, D:1} |
Idea (Kruskal). Sort edges cheapest-first; add an edge only if its endpoints are in different components (Union-Find), which avoids creating a cycle.
Trace on towns T1βT5. Edges sorted by weight; each is added or skipped based on the components:
| Step | Edge (w) uβv | roots find(u)/find(v) | Action | Components (Union-Find) | MST edges |
|---|---|---|---|---|---|
| 1 | (1) T2βT3 | T3 / T3 | ADD β | {T1}, {T2,T3}, {T4}, {T5} | T2T3 |
| 2 | (2) T2βT4 | T4 / T4 | ADD β | {T1}, {T2,T3,T4}, {T5} | T2T3, T2T4 |
| 3 | (3) T1βT3 | T4 / T4 | ADD β | {T1,T2,T3,T4}, {T5} | T2T3, T2T4, T1T3 |
| 4 | (4) T1βT2 | T4 / T4 | skip (cycle) | {T1,T2,T3,T4}, {T5} | T2T3, T2T4, T1T3 |
| 5 | (4) T3βT4 | T4 / T4 | skip (cycle) | {T1,T2,T3,T4}, {T5} | T2T3, T2T4, T1T3 |
| 6 | (5) T3βT5 | T5 / T5 | ADD β | {T1,T2,T3,T4,T5} | T2T3, T2T4, T1T3, T3T5 |
| 7 | (7) T4βT5 | T5 / T5 | skip (cycle) | {T1,T2,T3,T4,T5} | T2T3, T2T4, T1T3, T3T5 |
Idea (Prim). Grow a single tree from a seed town, each step pulling the cheapest edge from the heap that reaches a town not yet in the tree.
Trace from T1 β the heap holds candidate edges; skipped pops are edges to towns already connected:
| Step | Pop (w) uβv | Action | In tree | MST edges | Heap after |
|---|---|---|---|---|---|
| 0 | seed T1 | β | [T1] | β | [(3, 'T1', 'T3'), (4, 'T1', 'T2')] |
| 1 | pop (3) T1βT3 | ADD β | [T1, T3] | T1T3 | [(1, 'T3', 'T2'), (4, 'T1', 'T2'), (4, 'T3', 'T4'), (5, 'T3', 'T5')] |
| 2 | pop (1) T3βT2 | ADD β | [T1, T2, T3] | T1T3, T3T2 | [(2, 'T2', 'T4'), (4, 'T1', 'T2'), (4, 'T3', 'T4'), (5, 'T3', 'T5')] |
| 3 | pop (2) T2βT4 | ADD β | [T1, T2, T3, T4] | T1T3, T3T2, T2T4 | [(4, 'T1', 'T2'), (4, 'T3', 'T4'), (5, 'T3', 'T5'), (7, 'T4', 'T5')] |
| 4 | pop (4) T1βT2 | v already in tree β skip | [T1, T2, T3, T4] | T1T3, T3T2, T2T4 | [(4, 'T3', 'T4'), (5, 'T3', 'T5'), (7, 'T4', 'T5')] |
| 5 | pop (4) T3βT4 | v already in tree β skip | [T1, T2, T3, T4] | T1T3, T3T2, T2T4 | [(5, 'T3', 'T5'), (7, 'T4', 'T5')] |
| 6 | pop (5) T3βT5 | ADD β | [T1, T2, T3, T4, T5] | T1T3, T3T2, T2T4, T3T5 | [(7, 'T4', 'T5')] |
Idea. Visit vertices in some order; give each the smallest colour not used by its already-coloured neighbours.
The result depends on the order. Take the "crown" conflict graph β it is 2-colourable (two slots suffice). A bad alternating order forces a third slot:
| Step | Vertex | Neighbour colours used | Chosen | coloring |
|---|---|---|---|---|
| 1 | a1 | [] | 0 | {a1:0} |
| 2 | b1 | [] | 0 | {a1:0, b1:0} |
| 3 | a2 | [0] | 1 | {a1:0, b1:0, a2:1} |
| 4 | b2 | [0] | 1 | {a1:0, b1:0, a2:1, b2:1} |
| 5 | a3 | [0, 1] | 2 | {a1:0, b1:0, a2:1, b2:1, a3:2} |
| 6 | b3 | [0, 1] | 2 | {a1:0, b1:0, a2:1, b2:1, a3:2, b3:2} |
A better order (one whole side first) recovers the optimal two slots:
| Step | Vertex | Neighbour colours used | Chosen | coloring |
|---|---|---|---|---|
| 1 | a1 | [] | 0 | {a1:0} |
| 2 | a2 | [] | 0 | {a1:0, a2:0} |
| 3 | a3 | [] | 0 | {a1:0, a2:0, a3:0} |
| 4 | b1 | [0] | 1 | {a1:0, a2:0, a3:0, b1:1} |
| 5 | b2 | [0] | 1 | {a1:0, a2:0, a3:0, b1:1, b2:1} |
| 6 | b3 | [0] | 1 | {a1:0, a2:0, a3:0, b1:1, b2:1, b3:1} |
| Algorithm | State you track | Best for | Avoid when |
|---|---|---|---|
| BFS | queue, dist | fewest-hops path | weighted costs |
| DFS | stack / call stack, visited | explore, components, cycles | shortest path; very deep recursion |
| Topological sort | in-degree, queue / recursion | prerequisite ordering | graph has a cycle |
| Bipartite check | colour map, queue | two-group split / matching | odd cycles present |
| Dijkstra | dist, heap, settled set | cheapest path, weights β₯ 0 | negative weights |
| BellmanβFord | dist per pass | negative weights, cycle detection | large non-negative graphs (slow) |
| MST (Kruskal/Prim) | Union-Find / heap, tree edges | cheapest connecting network | shortest pairwise path |
| Greedy colouring | neighbour colours, colour map | fast conflict-free assignment | need provably minimum colours |
Notes By Pr. El Hadiq Zouhair
13 / 14Re-run each example by hand and check your variable states against these tables.
Notes By Pr. El Hadiq Zouhair
14 / 14