গ্রাফ রিপ্রেজেন্টেশন ও কানেক্টিভিটি
এই পাঠে যা শিখবেন
- Adjacency matrix ও adjacency list রিপ্রেজেন্টেশনের গঠন ও ট্রেডঅফ
- Walk, trail, path-এর সংজ্ঞা ও পার্থক্য
- Connected graph ও connected component-এর সংজ্ঞা
- BFS কীভাবে কানেক্টিভিটি যাচাইয়ে ব্যবহৃত হয় (concept-level)
- Python-এ BFS-ভিত্তিক কানেক্টিভিটি চেকার — সংযুক্ত ও বিচ্ছিন্ন উভয় গ্রাফে পরীক্ষা
১ · গ্রাফ কীভাবে সংরক্ষণ করা হয়?
L18-এ আমরা গ্রাফকে গাণিতিকভাবে সংজ্ঞায়িত করেছি। কিন্তু কম্পিউটারে একটি গ্রাফ প্রকৃতপক্ষে সংরক্ষণ করতে দুটি প্রধান পদ্ধতি ব্যবহৃত হয় —
$n \times n$ গ্রিড — এন্ট্রি 1 যদি edge থাকে, নাহলে 0। edge আছে কিনা তা $O(1)$ সময়ে জানা যায়, কিন্তু জায়গা লাগে $O(n^2)$ — sparse গ্রাফে অপচয়।
প্রতিটি vertex-এর একটি তালিকা — তার প্রতিবেশীরা কারা। জায়গা লাগে $O(\deg(v))$ — sparse গ্রাফের জন্য (কম edge থাকলে) অনেক বেশি জায়গা-সাশ্রয়ী।
২ · Walk, Trail, ও Path
একটি গ্রাফে এক vertex থেকে আরেক vertex-এ যাওয়ার "রাস্তা" বোঝাতে তিনটি ভিন্ন, সুনির্দিষ্ট পরিভাষা ব্যবহৃত হয় —
- WalkWalkvertex ও edge-এর যেকোনো ক্রম যেখানে পরপর প্রতিটি জোড়া edge দ্বারা সংযুক্ত — vertex ও edge পুনরাবৃত্তি করা যায়। — vertex-edge-vertex-...-এর যেকোনো ক্রম, vertex বা edge পুনরাবৃত্তি করা যায়।
- Trail — একটি walk যেখানে কোনো edge পুনরাবৃত্তি হয় না (vertex পুনরাবৃত্তি হতে পারে)।
- Path — একটি trail যেখানে কোনো vertex-ও পুনরাবৃত্তি হয় না।
L20-এ আমরা দেখব Euler path মূলত একটি বিশেষ ধরনের trail (প্রতিটি edge ব্যবহার করে, কিন্তু vertex পুনরাবৃত্তি হতে পারে), আর Hamiltonian path একটি প্রকৃত path (প্রতিটি vertex ঠিক একবার)।
৩ · কানেক্টিভিটি
একটি গ্রাফ connected হয় যদি প্রতিটি জোড়া vertex-এর মধ্যে অন্তত একটি path থাকে। যদি কোনো গ্রাফ connected না হয়, তাহলে সেটি কয়েকটি connected componentConnected componentএকটি গ্রাফের সর্বোচ্চ (maximal) connected উপ-গ্রাফ — যে vertex-গুলো নিজেদের মধ্যে path-এর মাধ্যমে পৌঁছানো যায়, কিন্তু বাকি গ্রাফের সাথে নয়।-এ ভাগ হয়ে যায় — প্রতিটি component নিজে সম্পূর্ণ connected, কিন্তু অন্য component-এর সাথে কোনো path নেই।
একটি গ্রাফ connected কিনা তা যাচাই করার standard পদ্ধতি হলো যেকোনো একটি vertex থেকে BFS (Breadth-First Search) বা DFS (Depth-First Search) চালিয়ে দেখা — সব vertex পৌঁছানো যায় কিনা। যদি সব vertex ভ্রমণ (visit) করা যায়, গ্রাফ connected; নাহলে অভ্রমিত vertex-গুলো অন্য component-এ। এই অ্যালগরিদমগুলোর সম্পূর্ণ বাস্তবায়ন ও জটিলতা বিশ্লেষণ DSA কোর্সের বিষয় — এখানে আমরা শুধু ধারণাটি ব্যবহার করছি।
from collections import deque
def is_connected(graph, start, all_vertices):
visited = {start}
queue = deque([start])
while queue:
v = queue.popleft()
for neighbor in graph.get(v, []):
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
return visited == set(all_vertices)
# গ্রাফ ১: সংযুক্ত (সবাই একে অপরের সাথে path-এ যুক্ত)
graph_connected = {
"A": ["B", "C"],
"B": ["A", "C"],
"C": ["A", "B", "D"],
"D": ["C"],
}
vertices1 = ["A", "B", "C", "D"]
print("গ্রাফ ১ সংযুক্ত (connected)?", is_connected(graph_connected, "A", vertices1))
# গ্রাফ ২: বিচ্ছিন্ন — {A,B} ও {C,D} দুটি আলাদা component
graph_disconnected = {
"A": ["B"],
"B": ["A"],
"C": ["D"],
"D": ["C"],
}
vertices2 = ["A", "B", "C", "D"]
print("গ্রাফ ২ সংযুক্ত (connected)?", is_connected(graph_disconnected, "A", vertices2))
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ কখন adjacency matrix, adjacency list-এর চেয়ে ভালো পছন্দ হতে পারে?
যখন গ্রাফটি dense (edge সংখ্যা $|V|^2$-এর কাছাকাছি) অথবা যখন বারবার "এই দুটি vertex-এর মধ্যে edge আছে কি না" এই প্রশ্নের $O(1)$ সময়ে উত্তর দরকার — তখন matrix-এর $O(n^2)$ জায়গার খরচ যুক্তিসঙ্গত, কারণ lookup speed-এর সুবিধা জায়গার খরচকে ছাপিয়ে যায়। বিপরীতে sparse গ্রাফে (যেমন একটি সোশ্যাল নেটওয়ার্ক যেখানে গড়ে প্রতিটি ব্যবহারকারীর কয়েকশ বন্ধু, কিন্তু কোটি কোটি সম্ভাব্য জোড়া) matrix বিশাল পরিমাণ মেমরি অপচয় করবে অধিকাংশ 0 সংরক্ষণ করে।
প্র ০২ একটি walk যেখানে edge পুনরাবৃত্তি নেই কিন্তু vertex পুনরাবৃত্তি আছে — এটি trail নাকি path? উদাহরণ দিন।
এটি একটি trail কিন্তু path নয় — কারণ path-এর শর্ত হলো vertex-ও পুনরাবৃত্তি হবে না। উদাহরণ — একটি চতুর্ভুজাকৃতি গ্রাফে A-B-C-D-A-এর মতো একটি ঘুরপথ যেখানে A দুইবার আসে (একবার শুরুতে, একবার শেষে) কিন্তু কোনো edge দুইবার ব্যবহৃত হয়নি — এটি একটি trail (আসলে একটি circuit, যেহেতু শুরু ও শেষ vertex একই)। L20-এ Euler circuit ঠিক এই ধরনের গঠন — অনেক vertex পুনরাবৃত্তি হতে পারে, কিন্তু কোনো edge নয়।
প্র ০৩ উপরের কোড সেলে গ্রাফ ২-এর জন্য ফলাফল False এসেছে। এর মানে কি গ্রাফ ২-তে কোনো গঠন/সংযোগ নেই?
না — False মানে গ্রাফটি সম্পূর্ণভাবে connected নয়, কিন্তু এর মানে এই নয় যে কোনো সংযোগই নেই। গ্রাফ ২-তে আসলে দুটি সম্পূর্ণ connected component আছে — {A, B} (একটি edge দ্বারা সংযুক্ত) এবং {C, D} (আরেকটি edge দ্বারা সংযুক্ত)। প্রতিটি component-এর ভেতরে সবকিছু connected, কিন্তু দুই component-এর মধ্যে কোনো path নেই — তাই সামগ্রিক গ্রাফ connected নয়। BFS শুধু start vertex-এর component-টুকু ভ্রমণ করতে পারে, বাকিটা নয়।
অনুশীলন
-
হাতে করুন: {A, B, C} vertex এবং {A-B, B-C} edge-বিশিষ্ট একটি গ্রাফের adjacency matrix হাতে লিখুন (3×3 গ্রিড, row/column ক্রম A,B,C)।
A B C
A [0, 1, 0]
B [1, 0, 1]
C [0, 1, 0]
A-B ও B-C-এর সাথে সঙ্গতিপূর্ণভাবে 1, বাকি সব 0 (A-C-এর মধ্যে সরাসরি edge নেই)। লক্ষ্য করুন matrix-টি symmetric — কারণ গ্রাফটি undirected। -
পরীক্ষা করুন: উপরের কোড সেলে
graph_connected-এ vertex "E" যোগ করুন যার কোনো প্রতিবেশী নেই ("E": []), এবংvertices1-এ "E" যোগ করুন।is_connectedএখন কী রিটার্ন করবে এবং কেন?রিটার্ন হবে
False— কারণ BFS শুধু "A"-এর সাথে সংযুক্ত component ভ্রমণ করে ({A, B, C, D}), কিন্তু বিচ্ছিন্ন vertex "E" কখনো visited সেটে যুক্ত হবে না। তাইvisited == set(all_vertices)মিথ্যা হয়ে যাবে — একটি সম্পূর্ণ বিচ্ছিন্ন (isolated) vertex-ও গ্রাফকে disconnected করে দেয়।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৪৪টি পাঠ পরবর্তী পাঠ — ইউলারিয়ান ও হ্যামিলটোনিয়ান পথ — এখনই পড়া যাবে।
- Data Structures & Algorithms কোর্স সঙ্গী কোর্স BFS/DFS-এর সম্পূর্ণ বাস্তবায়ন ও জটিলতা বিশ্লেষণ শিখতে DSA কোর্সটিও দেখুন।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, HTML & CSS ও Discrete Mathematics — সব এক জায়গায়।