3.5.6 · Coding › Graphs
Ek cycle ek aisi path hoti hai jo wahin waapis aati hai jahan se shuru hui thi. DFS naturally ek path ke saath "deep" explore karta hai, isliye yeh perfect tool hai jab hum accidentally kisi aise node par waapis chal dete hain jise hum abhi bhi visit kar rahe hote hain .
Directed aur undirected cases mein KEY difference yeh hai:
Directed: cycle tab exist karti hai jab DFS ko ek back edge mile — ek aisi edge jo kisi aise node ki taraf point kare jo currently recursion stack par hai (gray node).
Undirected: cycle tab exist karti hai jab DFS ko ek already-visited node tak jaane wali edge mile jo immediate parent nahi hai .
Definition DFS ke dauran node colors (states)
White = abhi tak visit nahi hua.
Gray = visit ho chuka hai, lekin uska DFS call abhi bhi stack par hai (hum uske descendants explore kar rahe hain).
Black = poori tarah finish (saare descendants explore ho gaye, stack se pop ho gaya).
Colors kyun matter karte hain (directed): Ek directed graph mein, kisi black node tak dobara pahunchna theek hai — iska sirf matlab hai ki do paths merge ho rahi hain (ek cross/forward edge), koi cycle nahi. Lekin kisi gray node tak pahunchna matlab hai ki tumne ek aisi path dhundh li jo ek aise ancestor ke paas loop back karti hai jiske andar tum abhi bhi ho → cycle.
Parent-exception kyun (undirected): Har undirected edge u − v dono taraf store hoti hai. Jab tum u → v jaate ho, tab v se tum u ki taraf wapas jaane wali edge dekhoge jo already visited hai. Yeh cycle NAHI hai — yeh wahi edge hai. Isliye tumhe immediate parent ko ignore karna padta hai. Lekin koi bhi doosra already-visited node dekhna ek genuine doosri path back ko indicate karta hai → cycle.
A → B → C → A
dfs(A): A=GRAY. Kyun? A mein enter kar rahe hain. → B ki taraf jao.
dfs(B): B=GRAY → C ki taraf jao.
dfs(C): C=GRAY. Neighbor A GRAY hai → True return karo. Yeh step kyun? Edge C → A ek aise node ki taraf point karti hai jo abhi bhi stack par hai = back edge = cycle. ✅
Worked example Directed, koi cycle NAHI:
A → B , A → C , B → C
A=GRAY → B=GRAY → C=GRAY → C done → C=BLACK, B=BLACK.
A mein waapis, C visit karo: C BLACK hai → skip karo (gray nahi). Yeh step kyun? A → C ek finished node ki taraf forward edge hai, loop nahi. Koi cycle nahi. ✅
Worked example Undirected: triangle
A − B − C − A
dfs(A, -1): A visit karo → B jao.
dfs(B, A): B visit karo → neighbors A(=parent, skip), C unvisited → C jao.
dfs(C, B): C visit karo → neighbor B parent hai (skip), neighbor A visited hai aur ≠ parent(B) → True return karo. Kyun? C − A A tak waapis jaane ka doosra raasta hai. ✅
Worked example Undirected tree (koi cycle nahi):
A − B , A − C
dfs(A,-1) → dfs(B,A): sirf neighbor A=parent, skip → waapis. dfs(C,A): sirf A=parent, skip → waapis. Koi cycle nahi. ✅ Kyun? n nodes wale tree mein exactly n − 1 edges hoti hain; koi bhi extra edge ek cycle create kar degi.
Common mistake Classic errors ko steel-man karna
Galti 1 — directed graphs par parent-trick use karna. Yeh sahi lagta hai ("jahan se aaya wahan se ignore karo"). Kyun fail hoti hai: directed edges symmetric nahi hoti; ignore karne ke liye koi spurious reverse edge nahi hai, aur ek sacchi 2-cycle A → B → A galat tarike se skip ho jaayegi. Fix: 3 colors use karo, GRAY check karo.
Galti 2 — undirected par GRAY/colors logic use karna aur parent bhool jaana. Tum HAR edge par immediate-parent reverse edge ko cycle flag kar doge. Kyun tempting lagta hai: "visited node reach hona = cycle" universal lagta hai. Fix: v != parent add karo.
Galti 3 — undirected mein parallel edges / self-loops. u , v ke beech do edges hone par, v != parent test cycle miss kar sakta hai. Fix: sirf parent nahi, edge-index visited track karo jab multigraphs allowed hoon. Ek self-loop u − u khud hi ek cycle hai.
Galti 4 — SAARE components par iterate na karna. Ek cycle ek disconnected component mein chupi ho sakti hai. Fix: for u: if not visited[u]: dfs(u) loop karo.
Recall Feynman: ek 12-saal ke bachche ko samjhao
Socho tum ek maze mein chal rahe ho aur peeche string khol rahe ho. Directed maze (one-way doors): agar ek darwaza tumhe ek aisi jagah le jaata hai jahan tumhari string abhi bhi zameen par padi hai saamne (tumne use abhi pack nahi kiya), tum ek chakkar mein gaye ho. Agar string wahan pehle se roll back ho chuki hai (tumne woh area finish kar liya), toh theek hai. Undirected maze (normal doors): har darwaze se guzarte waqt, peeche wala darwaza wahi hai jahan se tum aaye — use ignore karo! Lekin agar tum kisi aise room tak pahuncho jahan tum pehle se ja chuke ho ek alag darwaze se, toh maze mein ek loop hai.
"GRAY means STAY (on stack) → directed cycle. PARENT pardon → undirected cycle."
Directed: G ray = G otcha. Undirected: P arent skip karo, baaki kisi par P anic karo.
Directed graph: cycle tab exist karti hai jab DFS kaunsi tarah ki edge dhundhe? Ek back edge — ek aise node tak edge jo currently GRAY hai (recursion stack par).
Teen DFS colors WHITE/GRAY/BLACK ka kya matlab hai? White = unvisited; Gray = visited lekin abhi bhi recursion stack par; Black = poori tarah finished/popped.
Directed graph mein kisi BLACK node tak pahunchna cycle indicate kyun nahi karta? Black matlab us node ka DFS doosri branch par pehle hi finish ho chuka hai; woh edge ek cross/forward edge hai, live stack par loop back nahi.
Undirected cycle detection: DFS ke dauran cycle ki condition kya hai? Ek already-visited node tak edge jo immediate parent NAHI hai.
Undirected DFS mein v != parent check kyun? Har undirected edge dono directions mein store hoti hai; jis edge se hum aaye uski reverse copy falsely cycle jaisi dikhegi, isliye hum parent ko exclude karte hain.
Directed graphs ke liye parent-trick kyun use nahi kar sakte? Directed edges symmetric nahi hoti, isliye koi spurious reverse edge nahi hai; parent-trick ek sacchi 2-cycle A→B→A bhi miss kar degi.
DFS cycle detection ki time complexity? O(V + E), space O(V).
n nodes wale tree mein kitni edges hoti hain, aur ek extra edge kya karti hai? n−1 edges; koi bhi additional edge exactly ek cycle create karti hai.
Disconnected graphs mein cycles detect karna kaise ensure karte hain? Saare vertices par loop karo aur kisi bhi unvisited node se DFS shuru karo.
Sabse chhoti directed cycle aur sabse chhoti undirected cycle (simple)? Directed: 2 nodes (A→B→A) ya self-loop; Undirected (simple): 3 nodes (triangle).
Depth-First Search — woh traversal engine jis par yeh rely karte hain.
Topological Sort — tabhi possible hai jab directed graph acyclic ho (DAG); same back-edge test.
Union-Find (DSU) — DFS ke bina alternative undirected cycle detection.
Back Edges and Edge Classification — tree/back/forward/cross edges.
Strongly Connected Components — DFS finish times par built.
Bipartite Checking — ek aur DFS/BFS coloring application.
Cycle: path returns to start
Node colors White Gray Black
No cycle, cross or forward edge
Edge to visited non-parent node
visited array plus parent