ग्राफ में सबसे छोटा पथ निकालते समय, हम इसे अंत में पुनर्निर्मित भी कर सकते हैं।
इसके लिए, हम हर उस वर्टेक्स (शिखर) के लिए “parent” वर्टेक्स को सहेज सकते हैं, जिसे हम विज़िट करते हैं। मतलब, अगर हम किसी वर्टेक्स v को प्रोसेस करने के बाद वर्टेक्स to को कतार में जोड़ते हैं, तो हम यह चिह्नित कर सकते हैं कि to का “parent” वर्टेक्स v है। यह प्रक्रिया हमें अंत में पूरा पथ वापस ढूंढने में मदद करती है। हम पथ के अंतिम वर्टेक्स से शुरू करते हैं, उसके parent तक जाते हैं, फिर वर्तमान वर्टेक्स के parent तक जाते हुए तब तक चलते रहते हैं जब तक हमें ऐसा वर्टेक्स न मिल जाए जिसका कोई parent न हो—वही हमारा शुरुआती वर्टेक्स होगा। इसे एक अतिरिक्त parent array p रखकर आसानी से लागू किया जा सकता है:
start = int(input()) # start vertex
d = [-1] * n # distance from start vertex
p = [-1] * n # parent vertex
q = deque([start]) # queue of vertices
d[start] = 0 # distance from start to start is 0
while q: # while the queue is not empty
v = q.popleft() # get vertex from queue
print(v, end=' ') # print vertex
for to in g[v]: # for each vertex connected to v
if d[to] == -1: # if vertex is not visited
d[to] = d[v] + 1 # (start -> to) = (start -> v) + 1
p[to] = v # parent of vertex is v
q.append(to) # add vertex to queue
# Reconstruction of the path from start to end
end = int(input()) # end vertex
path = [] # path from start to end
while end != -1: # while there is a parent vertex
path.append(end) # add vertex to path
end = p[end] # go to parent vertex
print(*path[::-1], sep=' -> ') # print the path in reverse order
इस तरह, जब भी हम किसी नए वर्टेक्स को कतार में जोड़ते हैं, हम उसकी parent जानकारी p में दर्ज कर लेते हैं और फिर अंत में पथ को आखिरी वर्टेक्स से शुरू करके पहले तक वापस जाते हुए पुनर्निर्मित कर लेते हैं। अंतिम आउटपुट में, पथ को उल्टी दिशा से निकाला जाता है, इसलिए सही क्रम में प्रिंट करने के लिए हमें इसे रिवर्स करना पड़ता है।
आइए कुछ इनपुट पर इस एल्गोरिथ्म का एक छोटा सा सिमुलेशन करके देखें:
n = 4, e = 4
इनपुट (a, b) जोड़े इस प्रकार हैं: [(0, 1), (0, 2), (1, 2), (3, 2)]
शुरू करने वाला वर्टेक्स 3 है और अंतिम वर्टेक्स 0 है:
p = [-1, -1, -1, -1], q = [3]
v = 3, q = [] → 3 से जुड़े नए वर्टेक्स को कतार में जोड़ें
p = [-1, -1, 3, -1], q = [2]
v = 2, q = [] → 2 से जुड़े नए वर्टेक्स को कतार में जोड़ें
p = [2, 2, 3, -1], q = [0, 1]
v = 0, q = [1] → 0 से जुड़े नए वर्टेक्स को कतार में जोड़ें
v = 1, q = [] → 1 से जुड़े नए वर्टेक्स को कतार में जोड़ें
पथ पुनर्निर्माण करें
end = 0 → end = 2 → end = 3
अंत में प्रिंट करें: 3 → 2 → 0
ध्यान दें कि अगर एल्गोरिथ्म खत्म होने तक भी d[end] की वैल्यू -1 बनी रहती है, तो इसका मतलब है कि हम end वर्टेक्स तक नहीं पहुँच पाए।
चुनौती: सबसे छोटा रुट खोजें
इंटरनेट ऐसे कंप्यूटरों का एक समूह है जो एक-दूसरे से जुड़े हुए हैं और डेटा ट्रांसफर कर सकते हैं। यहाँ, कंप्यूटरों को 1 से n तक क्रमांकित किया गया है, और हमारे पास उन कंप्यूटरों की पेयर जानकारी है जो एक-दूसरे से जुड़े हैं। ऐलिस अपने कंप्यूटर (नंबर a) से बॉब (नंबर b) को एक संदेश भेजना चाहती है और चाहती है कि संदेश सबसे तेज़ी से पहुँचे। इसलिए, हमें सबसे छोटा रुट (पथ) ढूँढना होगा।
ऐलिस के कंप्यूटर का नंबर a है और बॉब के कंप्यूटर का नंबर b। आपका काम है कि इन कंप्यूटरों के बीच संदेश के आदान-प्रदान के लिए सबसे उपयुक्त (छोटा) रुट ढूँढें।
इनपुट
इनपुट की पहली पंक्ति में दो पूर्णांक n (1 ≤ n ≤ 100 000) और e (1 ≤ e ≤ 100 000) होते हैं, जो कंप्यूटरों की संख्या और नेटवर्क में कनेक्शन की संख्या दर्शाते हैं।
अगली पंक्ति में दो नंबर a और b (1 ≤ a, b ≤ n) दिए होते हैं।
इसके बाद की e पंक्तियों में दो पूर्णांक c1, c2 (1 ≤ c1, c2 ≤ n) होते हैं, जिनका मतलब है कि कंप्यूटर c1 और कंप्यूटर c2 आपस में जुड़े हैं (दो-तरफ़ा कनेक्शन)।
आउटपुट
कार्यक्रम को सबसे उपयुक्त (छोटा) ट्रांसफर रुट प्रिंट करना चाहिए, जहाँ हर कंप्यूटर नंबर को एक स्पेस से अलग करके दिखाया जाए। अगर ऐसे कई रुट संभव हों, तो कोई भी एक रुट प्रिंट किया जा सकता है।