এই পর্বে যা শিখবেন
- Simple graph, multigraph, pseudograph আর directed graph-এর নির্ভুল সংজ্ঞা, আর কোন উপপাদ্য কোন ধরনের graph-এর জন্য
- Handshake theorem আর তার corollary-র double counting প্রমাণ, directed graph-এর in/out-degree উপপাদ্যসহ
- Kn, Cn, Wn, Qn, Km,n আর regular graph-এর edge গোনা ও অস্তিত্বের শর্ত
- Bipartite ⇔ 2-colourable ⇔ বিজোড় cycle নেই, দুই দিকের সম্পূর্ণ প্রমাণ আর BFS-এ প্রমাণপত্র
- Degree sequence, Havel–Hakimi-র যুক্তি, subgraph, complement আর labelled graph গোনা
১ · গ্রাফ কী — vertex, edge আর চার ধরনের গ্রাফ
বাজারঘরের ডেলিভারি বিভাগের দেয়ালে একটি মানচিত্র ঝোলে: ঢাকার আশেপাশের কয়েকটি হাব, আর কোন দুটি হাবের মধ্যে সরাসরি ভ্যান চলে, তা দাগ টেনে দেখানো। দাগগুলো কত লম্বা, মানচিত্রে হাবটি ঠিক কোথায় আঁকা, এসব এখানে গুরুত্বহীন। প্রশ্ন শুধু একটি: কে কার সঙ্গে সরাসরি যুক্ত? এই “কে কার সঙ্গে যুক্ত” তথ্যটুকুর গাণিতিক রূপের নাম graph (গ্রাফ)। এখানে “graph” মানে ফাংশনের লেখচিত্র নয়, বরং একটি সংযোগ-কাঠামো।
একটি বিয়েবাড়ির কথা ভাবুন। অতিথিরা বিন্দু, আর দুজন অতিথি একে অন্যের সঙ্গে হাত মেলালে তাঁদের মধ্যে একটি দাগ। অনুষ্ঠান শেষে আপনি প্রত্যেক অতিথিকে জিজ্ঞেস করলেন “কতজনের সঙ্গে হাত মিলিয়েছেন?”, আর উত্তরগুলো যোগ করলেন। যোগফলটি সবসময় জোড় হবে, কারণ প্রতিটি করমর্দন দুজন মানুষ দুবার গুনেছেন। এই সরল পর্যবেক্ষণই এই পর্বের কেন্দ্রীয় উপপাদ্য, যার নাম এসেছে এই উদাহরণ থেকে: handshake theorem.
একটি simple graph G = (V, E) মানে একটি খালি-নয় সেট V, যার উপাদানকে বলে vertex (শীর্ষবিন্দু, বহুবচনে vertices), আর E হলো V-এর দুই-উপাদানের subset {u, v}-এর একটি সেট, যার প্রতিটিকে বলে edge (ধার)। edge {u, v}-কে সংক্ষেপে uv লেখা হয়; uv আর vu একই edge.
সংজ্ঞার দুটি শব্দ গুরুত্বপূর্ণ। “দুই-উপাদানের” মানে u ≠ v, তাই কোনো vertex নিজের সঙ্গে যুক্ত নয়। আর E একটি সেট, তাই একই জোড়া দুবার থাকতে পারে না। বাস্তবের অনেক নেটওয়ার্কে এই দুটি শর্তই ভাঙে, তাই আরও তিন ধরনের graph দরকার হয়:
| ধরন | edge-এ দিক | একই জোড়ায় একাধিক edge | loop | বাজারঘরের উদাহরণ |
|---|---|---|---|---|
| simple graph | না | না | না | কোন দুটি হাবের মধ্যে সরাসরি রাস্তা আছে |
| multigraph | না | হ্যাঁ | না | দুটি হাবের মধ্যে দুটি আলাদা রাস্তা (মহাসড়ক আর নদীপথ) |
| pseudograph | না | হ্যাঁ | হ্যাঁ | একই হাবের ভেতরে এক গুদাম থেকে আরেক গুদামে ঘুরে আসা রুট |
| directed graph | হ্যাঁ | বই অনুযায়ী | বই অনুযায়ী | একমুখী রাস্তা, বা “কে কাকে মাল পাঠায়” |
Multigraph-এ একই দুই vertex-এর মধ্যের একাধিক edge-কে বলে parallel edge, আর pseudograph-এর v থেকে v-তে ফেরা edge-কে loop (self-loop). এই দুটি সম্ভব করতে edge-কে আর শুধু একটি জোড়া হিসেবে দেখা যায় না; প্রতিটি edge-এর নিজস্ব নাম থাকে, আর একটি ফাংশন বলে দেয় তার দুই প্রান্ত কোন দুটি vertex. বইভেদে নামগুলো একটু আলাদা: অনেক বই “multigraph” বলতে loop-সহ graph-ও বোঝায়। তাই প্রতিটি উপপাদ্যের সঙ্গে স্পষ্ট লেখা থাকা দরকার কোন ধরনের graph-এর কথা হচ্ছে; এই পর্বে প্রতিটি উপপাদ্যে তা লেখা আছে, আর কিছু না বললে “graph” মানে simple, undirected graph.
- uv একটি edge হলে u আর v adjacent (সংলগ্ন), আর edge uv তার দুই প্রান্ত u আর v-এর সঙ্গে incident (সংযুক্ত)। Adjacency হলো vertex-vertex সম্পর্ক, incidence হলো vertex-edge সম্পর্ক।
- v-এর neighbourhood (প্রতিবেশী-সেট) N(v) = {u : uv ∈ E}.
- যে vertex-এর কোনো প্রতিবেশী নেই, সে isolated vertex; ঠিক একটি প্রতিবেশী থাকলে pendant vertex.
Adjacency সম্পর্কটি আসলে V-এর ওপর একটি relation: simple graph-এ এটি symmetric আর irreflexive, আর উল্টো দিকে V-এর ওপর যেকোনো symmetric, irreflexive relation একটি simple graph দেয়। Directed graph আর relation-এর একই সম্পর্ক পর্ব ৫২ “Relation আর তার ধর্ম”-এ দেখানো হয়েছে, আর graph-কে matrix হিসেবে লেখা পর্ব ১৯-এর adjacency matrix, যার বিস্তারিত পর্ব ৫৮ “গ্রাফের representation আর isomorphism”-এ আসবে।
নিচের ছবিটি এই পর্বের প্রথম চলমান উদাহরণ: বাজারঘরের ৬টি হাব আর ৮টি সরাসরি ভ্যান-রুট। হাবের নামগুলো শুধু লেবেল; রুটগুলো কাল্পনিক, বাস্তব রাস্তার মানচিত্র নয়।
বাজারঘরের হাব-নেটওয়ার্ক: ৬টি vertex, ৮টি edge
প্রতিটি বৃত্ত একটি হাব, প্রতিটি দাগ একটি সরাসরি রুট। বৃত্তের পাশের সংখ্যা তার degree; হলুদ বৃত্তের degree বিজোড়।
ছবিতে N(D) = {G, T, N, S, M}, N(N) = {D, S, M}. G আর T adjacent, কিন্তু G আর N নয়। কোনো isolated vertex নেই। গাণিতিকভাবে পুরো ছবিটি মাত্র দুটি সেট: V = {D, G, T, N, S, M} আর E = {DG, DT, DN, DS, DM, GT, NS, NM}.
২ · Degree আর handshake theorem
Undirected graph (simple, multi বা pseudo)-এ vertex v-এর degree deg(v) মানে v-এর সঙ্গে incident edge-এর সংখ্যা, যেখানে v-এর প্রতিটি loop ২ বার গোনা হয়। Simple graph-এ deg(v) = |N(v)|. সবচেয়ে ছোট degree-কে δ(G) আর সবচেয়ে বড়টিকে Δ(G) লেখা হয়।
Loop দুবার গোনার নিয়মটি খেয়ালখুশি নয়: একটি loop v-কে দুটি “প্রান্ত” দেয়, ঠিক অন্য যেকোনো edge-এর মতো। এই নিয়মেই নিচের উপপাদ্যটি loop-সহ সব graph-এ সত্য থাকে।
G = (V, E) যেকোনো সসীম undirected graph (simple, multigraph বা pseudograph) হলে
∑v ∈ V deg(v) = 2|E|
প্রমাণ (double counting). পর্ব ৩৭ “গণনার কৌশল”-এর double counting কৌশলে একটি সেট দুইভাবে গুনি। সেটটি হলো সব “প্রান্ত-জোড়া” (v, e), যেখানে v হলো edge e-এর একটি প্রান্ত; loop-এর ক্ষেত্রে v-কে দুটি আলাদা প্রান্ত হিসেবে ধরা হয়।
- Vertex ধরে গুনলে: v-কে প্রান্ত হিসেবে পাওয়া যায় ঠিক deg(v)বার, কারণ degree-র সংজ্ঞায় loop দুবার গোনা হয়। মোট ∑ deg(v). — সংজ্ঞা ২.১
- Edge ধরে গুনলে: প্রতিটি edge-এর ঠিক দুটি প্রান্ত (loop-এর দুটি প্রান্ত একই vertex), তাই মোট 2|E|. — edge-এর সংজ্ঞা
- একই সসীম সেট দুইভাবে গোনা হয়েছে, আর প্রতিটি পদ্ধতিতে প্রতিটি প্রান্ত-জোড়া ঠিক একবার এসেছে, তাই দুটি সংখ্যা সমান। ∎ — double counting
যেকোনো সসীম undirected graph-এ বিজোড় degree-র vertex-এর সংখ্যা জোড়।
- V-কে দুই ভাগে ভাগ করুন: Vodd (বিজোড় degree) আর Veven (জোড় degree). — partition
- উপপাদ্য ২.২ থেকে ∑Vodd deg(v) = 2|E| − ∑Veven deg(v). ডানের দুটি পদই জোড়, তাই বাঁ দিক জোড়। — জোড় − জোড় = জোড়
- বাঁ দিকটি |Vodd|টি বিজোড় সংখ্যার যোগফল। বিজোড় সংখ্যক বিজোড় সংখ্যার যোগফল বিজোড়, তাই |Vodd| জোড় হতেই হবে। ∎ — parity
নিচের stepper হাব-নেটওয়ার্কের ৮টি edge দুটি দুটি করে যোগ করে, আর প্রতি ধাপে degree, তাদের যোগফল আর বিজোড় vertex-এর সংখ্যা দেখায়। লক্ষ করুন, প্রতিটি নতুন edge যোগফলে ঠিক 2 যোগ করে, আর বিজোড় vertex-এর সংখ্যা 2 বাড়ে, 2 কমে বা একই থাকে, কখনো 1 বদলায় না।
1শুরু: কোনো edge নেই2+ DG, DN3+ DS, DT4+ GT, NM5+ DM, NS6∑deg = 2m যাচাই
| deg | |
| m | |
| ∑deg | |
| বিজোড় |
- শুরু। ৬টি হাব, কোনো রুট নেই। সবার degree 0, যোগফল 0 = 2 × 0, আর কোনো vertex বিজোড় নয়।
- DG আর DN. প্রতিটি edge তার দুই প্রান্তের degree 1 করে বাড়ায়: D পায় 2, G আর N পায় 1 করে। যোগফল 4 = 2 × 2. বিজোড় এখন G আর N, দুজন।
- DS আর DT. D-এর degree 4, S আর T-এর 1. যোগফল 8 = 2 × 4. বিজোড় vertex G, N, S, T: চারজন, এখনো জোড় সংখ্যা।
- GT আর NM. GT যোগে G আর T দুজনেই জোড় হলো (বিজোড়-সংখ্যা 2 কমল)। NM যোগে N জোড় হলো, M বিজোড় হলো (সংখ্যা একই থাকল)। বিজোড় এখন S আর M. যোগফল 12 = 2 × 6.
- DM আর NS. D-এর degree 5 (বিজোড়), M-এর 2; N-এর 3 (বিজোড়), S-এর 2. শেষ degree তালিকা D 5, G 2, N 3, S 2, T 2, M 2.
- যাচাই। 5 + 2 + 3 + 2 + 2 + 2 = 16 = 2 × 8. বিজোড় vertex D আর N, দুজন। প্রতিটি edge দুটি vertex-এর parity উল্টায়, তাই বিজোড়দের সংখ্যা সবসময় ২-এর গুণিতকে বদলায়: এটিই corollary ২.৩-এর দ্বিতীয় একটি প্রমাণ (edge-সংখ্যার ওপর induction).
এবার দাবিটি অনেক graph-এ একসঙ্গে পরীক্ষা করি: loop আর parallel edge-সহ এলোমেলো pseudograph, একটি এলোমেলো directed graph, আর ৫টি নামযুক্ত vertex-এর সব 210 = 1024টি simple graph. প্রথমবার চালালে ব্রাউজারে Python (Pyodide) নামতে কয়েক সেকেন্ড লাগে; পরের ব্লকগুলো দ্রুত চলে।
import random
from collections import Counter
from itertools import combinations, product
random.seed(57)
def degrees(n, edges): # a loop (v, v) adds 2 to deg(v)
deg = [0] * n
for u, v in edges:
deg[u] += 1
deg[v] += 1
return deg
for trial in range(5): # random multigraphs with loops
n, m = random.randint(4, 9), random.randint(3, 15)
edges = [(random.randrange(n), random.randrange(n)) for _ in range(m)]
deg = degrees(n, edges)
odd = sum(d % 2 for d in deg)
loops = sum(u == v for u, v in edges)
print(f"n={n} m={m:2} loops={loops} degrees={deg}"
f" sum={sum(deg):2} 2m={2 * m:2} odd={odd}")
n, m = 7, 12 # a random directed graph
arcs = [(random.randrange(n), random.randrange(n)) for _ in range(m)]
out_deg = Counter(u for u, v in arcs)
in_deg = Counter(v for u, v in arcs)
print("digraph: sum out =", sum(out_deg.values()),
" sum in =", sum(in_deg.values()), " m =", m)
pairs = list(combinations(range(5), 2)) # all 2^10 simple graphs, n = 5
tally = Counter()
for bits in product((0, 1), repeat=len(pairs)):
deg = degrees(5, [p for p, b in zip(pairs, bits) if b])
tally[sum(d % 2 for d in deg)] += 1
print("graphs on 5 vertices by number of odd vertices:",
dict(sorted(tally.items())))আসল আউটপুট (ব্রাউজারের Python):
n=4 m= 8 loops=1 degrees=[3, 3, 4, 6] sum=16 2m=16 odd=2
n=8 m= 5 loops=0 degrees=[0, 0, 3, 2, 1, 1, 3, 0] sum=10 2m=10 odd=4
n=7 m=13 loops=2 degrees=[6, 1, 5, 7, 4, 2, 1] sum=26 2m=26 odd=4
n=6 m=13 loops=1 degrees=[5, 5, 3, 3, 2, 8] sum=26 2m=26 odd=4
n=4 m= 7 loops=2 degrees=[4, 7, 1, 2] sum=14 2m=14 odd=2
digraph: sum out = 12 sum in = 12 m = 12
graphs on 5 vertices by number of odd vertices: {0: 64, 2: 640, 4: 320}
প্রথম পাঁচ লাইনের প্রতিটিতে sum আর 2m হুবহু সমান, এমনকি loop থাকলেও (loop (v, v) কোডে deg[v]-তে দুবার 1 যোগ করে, ঠিক সংজ্ঞা ২.১-এর মতো)। odd কলামে শুধু 2 আর 4. Directed graph-এ out আর in-এর যোগফল দুটিই edge-সংখ্যা 12, যার প্রমাণ পরের অংশে। শেষ লাইনটি সবচেয়ে জোরালো: ৫টি vertex-এর ১০২৪টি graph-এর একটিতেও বিজোড় vertex ১, ৩ বা ৫টি নেই; ৬৪টিতে ০, ৬৪০টিতে ২, আর ৩২০টিতে ৪. 64 + 640 + 320 = 1024. (৬৪টির সব degree জোড়, আর এটি 2C(4,2) = 64-এর সমান; অনুশীলনের মতো একটি সুন্দর প্রশ্ন হলো কেন।)
৩ · Directed graph — in-degree আর out-degree
বাজারঘরের কিছু রুট একমুখী: ভ্যান মূল গুদাম থেকে হাবে যায়, ফেরে অন্য পথে। এমন সংযোগের জন্য edge-কে ক্রমজোড়া (u, v) হিসেবে লেখা হয়, যার অর্থ u থেকে v-তে একটি তীর (arc). u হলো তীরের শুরু (tail), v শেষ (head).
Directed graph G = (V, E)-এ v-এর in-degree deg−(v) = v-তে শেষ হওয়া তীরের সংখ্যা, আর out-degree deg+(v) = v থেকে শুরু হওয়া তীরের সংখ্যা। একটি loop (v, v) দুটিতেই 1 যোগ করে। তাহলে যেকোনো সসীম directed graph-এ (parallel তীর আর loop থাকলেও)
∑v deg−(v) = ∑v deg+(v) = |E|
- প্রতিটি তীরের ঠিক একটি শুরু আছে। তাই তীরগুলোকে শুরুর vertex অনুযায়ী ভাগ করলে v-এর ভাগে deg+(v)টি তীর, আর ভাগগুলো মিলে সব তীর: ∑ deg+(v) = |E|. — partition ধরে গোনা
- প্রতিটি তীরের ঠিক একটি শেষ আছে; একই যুক্তিতে ∑ deg−(v) = |E|. ∎ — একই যুক্তি
উদাহরণ: তীরগুলো D→G, D→N, G→T, T→D, N→M, M→D, S→D. তাহলে deg+: D 2, G 1, T 1, N 1, M 1, S 1 (যোগফল 7); deg−: D 3, G 1, N 1, T 1, M 1, S 0 (যোগফল 7). S থেকে শুধু বের হওয়া যায়, ঢোকা যায় না: এমন vertex (in-degree 0)-কে source বলে, আর out-degree 0 হলে sink. পর্ব ৫৬-এর topological sort ঠিক in-degree 0 vertex থেকে শুরু করে।
একটি সাধারণ ভুল: “directed graph-এ সব degree-র যোগফল 2|E|” লিখে in-degree-র যোগফলকেই 2|E| ধরা। সঠিক কথা: in আর out আলাদাভাবে প্রতিটি |E|; দুটি মিলিয়ে (তীরের দিক ভুলে গেলে যে undirected graph পাওয়া যায়, তার degree) 2|E|.
৪ · চেনা পরিবার — Kn, Cn, Wn, Qn আর regular graph
কিছু graph এত ঘনঘন আসে যে তাদের নিজস্ব নাম আছে। নিচের প্রতিটি simple graph, আর প্রতিটির edge-সংখ্যা handshake theorem থেকে এক লাইনে বের হয়।
| নাম | গঠন | vertex | degree | edge |
|---|---|---|---|---|
| complete graph Kn | প্রতিটি জোড়া যুক্ত | n | সবার n − 1 | n(n − 1)/2 = C(n, 2) |
| cycle Cn (n ≥ 3) | v1v2, …, vn−1vn, vnv1 | n | সবার 2 | n |
| wheel Wn (n ≥ 3) | Cn + একটি hub, সবার সঙ্গে যুক্ত | n + 1 | রিমে 3, hub-এ n | 2n |
| hypercube Qn | n-বিট string; ঠিক এক বিটে আলাদা হলে যুক্ত | 2n | সবার n | n · 2n−1 |
| complete bipartite Km,n | m আর n-এর দুই দল, দলের বাইরে সব জোড়া | m + n | এক দলে n, অন্যে m | mn |
একটি উদাহরণ প্রমাণ: Qn-এ প্রতিটি vertex একটি n-বিট string, আর প্রতিটি বিট উল্টে ঠিক n জন প্রতিবেশী পাওয়া যায়। তাই ∑ deg = n · 2n = 2|E|, অর্থাৎ |E| = n · 2n−1. Q3 সাধারণ ঘনক (৮টি কোণ, ১২টি ধার)। পর্ব ৩৬-এর Gray code আসলে Qn-এর সব vertex একবার করে ছুঁয়ে যাওয়া একটি পথ, যা পর্ব ৬০ “Euler আর Hamilton path”-এ আবার আসবে। নামকরণে সাবধান: এখানে (Rosen-এর বইয়ের মতো) Wn-এ n + 1টি vertex; কিছু বই Wn বলতে মোট n vertex-এর wheel বোঝায়। পরীক্ষায় প্রশ্নের সংজ্ঞাটি আগে দেখে নিন।
ছয়টি চেনা graph
n = vertex-সংখ্যা, m = edge-সংখ্যা। Bipartite দুটিতে নীল আর হলুদ দুই দল; W5-এর হলুদ বৃত্তটি hub. Q3-এর বৃত্তে 0–7 লেখা, যার মানে তিন-বিটের সংখ্যা 000–111; ঠিক এক বিটে আলাদা হলে edge.
যে graph-এর সব vertex-এর degree k, তাকে k-regular graph বলে। n-টি vertex-এর একটি k-regular simple graph আছে যদি এবং কেবল যদি 0 ≤ k ≤ n − 1 আর nk জোড়।
- প্রয়োজনীয়তা: simple graph-এ একটি vertex-এর প্রতিবেশী বড়জোর বাকি n − 1 জন, তাই k ≤ n − 1. আর handshake theorem অনুযায়ী nk = ∑ deg = 2|E|, জোড়। — উপপাদ্য ২.২
- যথেষ্টতা, k জোড় হলে: vertex 0, 1, …, n − 1 নিন, আর i-কে i ± 1, i ± 2, …, i ± k/2 (mod n)-এর সঙ্গে যুক্ত করুন। k/2 < n/2, তাই এই k-টি সংখ্যা আলাদা আর 0 নয় (mod n), অর্থাৎ প্রত্যেকের ঠিক k জন প্রতিবেশী। — mod n হিসাব (পর্ব ২২)
- k বিজোড় হলে nk জোড় হওয়ায় n জোড়। ধাপ ২-এর গঠন k − 1-এর জন্য করে প্রতিটি i-কে i + n/2-এর সঙ্গেও যুক্ত করুন। (k − 1)/2 < n/2, তাই এই নতুন প্রতিবেশী আগের কারও সঙ্গে মেলে না, আর i + n/2 + n/2 ≡ i বলে সম্পর্কটি দুই দিকে একই। সবার degree k. ∎ — গঠন দিয়ে প্রমাণ
তাই ৭টি vertex-এ কোনো 3-regular graph নেই (7 × 3 = 21 বিজোড়), কিন্তু 2-, 4- বা 6-regular আছে। বাজারঘরের ভাষায়: ৭টি হাবের প্রত্যেককে ঠিক ৩টি অন্য হাবের সঙ্গে সরাসরি জোড়ার পরিকল্পনা কাগজে যত সুন্দরই দেখাক, বাস্তবায়ন অসম্ভব। §৭-এর কোডে ছোট n-এর জন্য সব regular graph গুনে এই উপপাদ্য মেলানো হয়েছে।
৫ · Bipartite graph — দুই দল, দুই রং আর বিজোড় cycle
বাজারঘরের কর্মী-শিফট তালিকায় দুই ধরনের বস্তু: কর্মী আর শিফট। একজন কর্মী যে শিফটে কাজ করতে পারেন, সেখানে একটি edge. এখানে কোনো edge দুজন কর্মীকে বা দুটি শিফটকে জোড়ে না। এই ধরনের graph-এর নাম bipartite graph, আর কর্মীদের শিফটে বসানোর গণিত (matching) আসবে পর্ব ৬৪ “Matching — bipartite graph, Hall-এর উপপাদ্য আর stable matching”-এ।
- G = (V, E) bipartite, যদি V-কে দুটি বিচ্ছিন্ন সেট V1, V2-এ ভাগ করা যায় (একটি খালি হতে পারে), যাতে প্রতিটি edge-এর এক প্রান্ত V1-এ আর অন্যটি V2-এ।
- G-এর একটি proper colouring মানে প্রতিটি vertex-কে একটি রং দেওয়া, যাতে কোনো edge-এর দুই প্রান্তে একই রং না পড়ে। দুটি রঙে সম্ভব হলে G 2-colourable.
- একটি path মানে পরপর edge দিয়ে যুক্ত আলাদা আলাদা vertex-এর ক্রম v0, v1, …, vk, যার দৈর্ঘ্য k (edge-সংখ্যা)। একটি cycle মানে k ≥ 3-এর এমন একটি path, যার শেষ vertex শুরুর সঙ্গে যুক্ত; এর দৈর্ঘ্য k + 1. দৈর্ঘ্য বিজোড় হলে odd cycle. (Walk, trail আর path-এর পুরো সংজ্ঞা আর ধর্ম পর্ব ৫৯ “Connectivity”-তে।)
উদাহরণ: C6 bipartite (vertex একটির পর একটি নীল-হলুদ), C5 নয়। Qn bipartite: যে string-এ 1-এর সংখ্যা জোড় সেগুলো এক দলে, বিজোড়গুলো অন্য দলে, আর একটি বিট উল্টালে parity বদলায়। K3 (ত্রিভুজ) নয়, তাই কোনো wheel নয়, কারণ hub আর রিমের দুটি পাশাপাশি vertex একটি ত্রিভুজ বানায়।
Loop নেই এমন যেকোনো undirected graph G-এর জন্য নিচের তিনটি কথা সমতুল্য: (ক) G bipartite; (খ) G 2-colourable; (গ) G-এ কোনো odd cycle নেই।
(ক) ⇔ (খ). V1-এর সবাইকে নীল আর V2-এর সবাইকে হলুদ রং দিলে proper colouring পাওয়া যায়; উল্টো দিকে একটি 2-colouring-এর দুই রঙের vertex-গুলোই দুটি দল। দুটি কথা আসলে একই তথ্যের দুই নাম। ∎
(খ) ⇒ (গ).
- ধরুন v0v1⋯vk−1v0 একটি cycle, দৈর্ঘ্য k, আর একটি proper 2-colouring আছে। — অনুমান
- পরপর দুটি vertex edge দিয়ে যুক্ত, তাই রং পালাক্রমে বদলায়: vi-এর রং v0-এর রঙের সমান ঠিক যখন i জোড়। — proper colouring, i-এর ওপর induction
- শেষ edge vk−1v0, তাই vk−1-এর রং v0-এর থেকে আলাদা, অর্থাৎ k − 1 বিজোড়, k জোড়। কোনো cycle বিজোড় নয়। ∎ — ধাপ ২
(গ) ⇒ (খ). এটিই আসল কাজের দিক, কারণ এখানে রং “বানাতে” হয়।
- প্রতিটি connected অংশ (component) আলাদাভাবে রং করলেই হয়, কারণ ভিন্ন অংশের মধ্যে কোনো edge নেই। তাই ধরুন G connected; একটি vertex r বেছে নিন। — অংশে ভাগ (পর্ব ৫৫-এর equivalence class)
- প্রতিটি v-এর জন্য d(v) = r থেকে v-এর সবচেয়ে ছোট path-এর দৈর্ঘ্য। d(v) জোড় হলে v নীল, বিজোড় হলে হলুদ। — দূরত্বের parity দিয়ে রং
- ধরুন কোনো edge uv-এর দুই প্রান্তে একই রং। যেকোনো edge uv-এর জন্য |d(u) − d(v)| ≤ 1 (u পর্যন্ত পথের সঙ্গে uv জুড়লে v-তে পৌঁছানো যায়), তাই একই parity মানে d(u) = d(v) = d. — বিপরীত অনুমান
- r থেকে u-তে একটি সবচেয়ে ছোট path P আর v-তে একটি সবচেয়ে ছোট path Q নিন। P আর Q-এর সাধারণ vertex-গুলোর মধ্যে r থেকে সবচেয়ে দূরেরটি w. যেকোনো সাধারণ vertex x দুটি path-এই r থেকে ঠিক d(x) দূরত্বে বসে, তাই w-এর পরে P আর Q আর মেলে না। — সবচেয়ে ছোট path-এর অংশও সবচেয়ে ছোট
- P-এর w থেকে u পর্যন্ত অংশ (দৈর্ঘ্য d − d(w)), edge uv, আর Q-এর v থেকে w পর্যন্ত অংশ (দৈর্ঘ্য d − d(w)) মিলে একটি cycle, কারণ তারা শুধু w-এ মেলে আর u ≠ v. তার দৈর্ঘ্য 2(d − d(w)) + 1, বিজোড়। — ধাপ ৪
- এটি অনুমান (গ)-এর বিরোধী। তাই কোনো edge-এর দুই প্রান্তে একই রং নেই, আর ধাপ ২-এর রং একটি proper 2-colouring. ∎ — contradiction
প্রমাণটি গঠনমূলক: এটি একটি algorithm বলে দেয়। BFS (breadth-first search) r থেকে স্তরে স্তরে vertex খুঁজে ঠিক d(v) বের করে (DSA কোর্সের পর্ব ৪০-এ কোড আর জটিলতা)। স্তরের parity দিয়ে রং দিন; কোথাও একই রঙের দুই প্রান্তের edge পেলে ধাপ ৪–৫ অনুযায়ী parent-এর শিকল ধরে পেছনে গিয়ে একটি odd cycle বের করুন। নিচের stepper এটি ৭টি হাবের একটি graph-এ দেখায়, যার edge AB, AC, BD, CE, DE, DF, FG.
1A লাল, queue = [A]2A বের: B, C নীল3B বের: D লাল4C বের: E লাল5D বের: D–E দুজনেই লাল!6parent ধরে odd cycle
| লাল | |
| নীল | |
| queue | |
| parent |
- শুরু। মূল vertex r = A, d(A) = 0, রং লাল। queue-তে শুধু A.
- A-এর প্রতিবেশী। B আর C আগে দেখা হয়নি; দুজনকেই নীল রং (d = 1), parent A. queue এখন B, C.
- B-এর প্রতিবেশী। A আগেই লাল, B নীল: ঠিক আছে। D নতুন: লাল (d = 2), parent B.
- C-এর প্রতিবেশী। A ঠিক আছে। E নতুন: লাল (d = 2), parent C. queue এখন D, E.
- দ্বন্দ্ব। D-এর প্রতিবেশী B নীল (ঠিক), কিন্তু E-ও লাল, D-ও লাল। DE edge-এর দুই প্রান্ত একই রঙে, আর দুজনেই স্তর 2-এ: উপপাদ্যের ধাপ ৩-এর অবস্থা।
- প্রমাণপত্র। parent ধরে ওঠা: D → B → A আর E → C → A. শেষ সাধারণ vertex w = A. cycle D, B, A, C, E (তারপর E থেকে D-তে ফেরা), দৈর্ঘ্য 2 + 2 + 1 = 5, বিজোড়। তাই graph-টি bipartite নয়, আর যে কেউ ৫টি edge মিলিয়ে কথাটি যাচাই করতে পারেন।
এই “প্রমাণপত্র” (certificate) ধারণাটি গুরুত্বপূর্ণ। “হ্যাঁ, bipartite” উত্তরের সঙ্গে একটি 2-colouring দেওয়া যায়, যা প্রতিটি edge দেখে যাচাই হয়। “না” উত্তরের সঙ্গে একটি odd cycle দেওয়া যায়, যা (খ) ⇒ (গ) অনুযায়ী যেকোনো 2-colouring-কে অসম্ভব করে। দুই দিকেই উত্তর বিশ্বাস করতে algorithm-এর কোড পড়তে হয় না। নিচের কোড ঠিক এটি করে, আর ফলাফল 2nটি রং-বিন্যাস সব পরীক্ষা করা brute force-এর সঙ্গে মেলায়।
from collections import deque
def two_colour(adj): # (colouring, None) or (None, odd cycle)
colour, parent = {}, {}
for s in adj: # restart in every component
if s in colour: continue
colour[s], parent[s] = 0, None
q = deque([s])
while q:
u = q.popleft()
for v in adj[u]:
if v not in colour:
colour[v], parent[v] = 1 - colour[u], u
q.append(v)
elif colour[v] == colour[u]: # same BFS level
pu, pv = [u], [v]
while parent[pu[-1]] is not None: pu.append(parent[pu[-1]])
while parent[pv[-1]] is not None: pv.append(parent[pv[-1]])
w = next(x for x in pu if x in pv) # last common ancestor
return None, pu[:pu.index(w) + 1] + pv[:pv.index(w)][::-1]
return colour, None
def graph(edges):
adj = {}
for u, v in edges: adj.setdefault(u, []).append(v); adj.setdefault(v, []).append(u)
return {u: sorted(adj[u]) for u in sorted(adj)}
def brute(adj): # try all 2^n colourings
return any(all(c[u] != c[v] for u in adj for v in adj[u])
for c in ({v: m >> i & 1 for i, v in enumerate(adj)} for m in range(2 ** len(adj))))
tests = {"hubs": graph(zip("AABCDDF", "BCDEEFG")),
"Q3": graph((x, x ^ b) for x in range(8) for b in (1, 2, 4)),
"Petersen": graph([(i, (i + 1) % 5) for i in range(5)] + [(i, i + 5) for i in range(5)]
+ [(5 + i, 5 + (i + 2) % 5) for i in range(5)])}
for name, adj in tests.items():
col, cyc = two_colour(adj)
ok = cyc is None or (len(cyc) % 2 == 1 and all(cyc[i - 1] in adj[cyc[i]] for i in range(len(cyc))))
print(f"{name}: bipartite={col is not None} brute={brute(adj)} certificate={cyc} checked={ok}")আসল আউটপুট (ব্রাউজারের Python):
hubs: bipartite=False brute=False certificate=['D', 'B', 'A', 'C', 'E'] checked=True
Q3: bipartite=True brute=True certificate=None checked=True
Petersen: bipartite=False brute=False certificate=[2, 1, 0, 4, 3] checked=True
হাব-graph-এর certificate হুবহু stepper-এর cycle: D, B, A, C, E. Q3-এর জন্য কোনো certificate নেই, কারণ সেটি bipartite. Petersen graph (১০টি vertex, ১৫টি edge, যার বিস্তারিত পর্ব ৫৮-এ) bipartite নয়, আর BFS তার বাইরের পঞ্চভুজ 2, 1, 0, 4, 3 খুঁজে দিয়েছে। প্রতিটি লাইনে brute force একই উত্তর দিয়েছে, আর checked=True মানে certificate-টি সত্যিই একটি বিজোড় দৈর্ঘ্যের বন্ধ পথ, যার প্রতিটি পরপর জোড়া graph-এ adjacent. Brute force-এ 2nটি বিন্যাস লাগে (Petersen-এ 1024), অথচ BFS প্রতিটি edge মাত্র দুবার দেখে; n = 60 হলে brute force-এর 260 ধাপ অসম্ভব, BFS তখনও মুহূর্তের কাজ। তিন রঙে রং করার প্রশ্নে কিন্তু এমন দ্রুত পদ্ধতি জানা নেই: সেটি NP-complete (DSA কোর্সের পর্ব ৬৪), যা পর্ব ৬৩ “Graph coloring”-এ আসবে।
৬ · Degree sequence — কোন তালিকা দিয়ে graph বানানো যায়?
একটি graph-এর সব degree বড় থেকে ছোট সাজিয়ে লিখলে পাওয়া যায় তার degree sequence; হাব-graph-এর জন্য (5, 3, 2, 2, 2, 2). উল্টো প্রশ্নটি বেশি মজার: একজন ম্যানেজার বললেন “৭টি হাবের রুট-সংখ্যা হবে 3, 3, 2, 2, 2, 1, 1”, এমন simple graph কি আছে? যে তালিকার জন্য আছে, তাকে graphical বলে।
Handshake থেকে প্রথম শর্ত: যোগফল জোড় হতে হবে। কিন্তু শর্তটি যথেষ্ট নয়। (3, 3, 3, 1)-এর যোগফল 10, জোড়, অথচ graph নেই: তিনটি degree-3 vertex-এর প্রত্যেককে বাকি তিনজনের সবার সঙ্গে যুক্ত হতে হবে, তাহলে চতুর্থজনের degree 3 হয়, 1 নয়। সাধারণ উত্তর দেয় নিচের উপপাদ্য, যা Václav Havel (১৯৫৫) আর S. L. Hakimi (১৯৬২) আলাদাভাবে প্রকাশ করেন বলে সাধারণত উল্লেখ করা হয়।
ধরুন d1 ≥ d2 ≥ ⋯ ≥ dn ≥ 0 পূর্ণসংখ্যা আর d1 ≤ n − 1. তালিকা d graphical (simple graph-এর জন্য) যদি এবং কেবল যদি নিচের তালিকা d′ graphical: প্রথম পদ d1 বাদ দিয়ে পরের d1টি পদ থেকে 1 করে কমানো, বাকিগুলো অপরিবর্তিত:
d′ = (d2 − 1, …, dd1+1 − 1, dd1+2, …, dn)
এই উপপাদ্য একটি algorithm দেয়, যার নাম Havel–Hakimi algorithm: বারবার সবচেয়ে বড় পদ সরিয়ে পরের পদগুলো কমান আর নতুন করে সাজান। কোনো পদ ঋণাত্মক হলে, বা বাকি পদের চেয়ে বেশি কমাতে হলে “না”; সব পদ 0 হলে “হ্যাঁ”. প্রমাণের রূপরেখা (পূর্ণ প্রমাণ নিচের ধাপগুলোতে প্রায় সম্পূর্ণ):
- (⇐) d′ কোনো graph H-এ বাস্তবায়িত হলে H-এ একটি নতুন vertex v1 যোগ করে d′-এর প্রথম d1টি vertex-এর সঙ্গে যুক্ত করুন। তাদের degree 1 করে বাড়ে, v1-এর degree d1: d পাওয়া গেল। — সরাসরি গঠন
- (⇒) d কোনো graph G-এ বাস্তবায়িত হলে, সব বাস্তবায়নের মধ্যে এমন G নিন যেখানে v1-এর প্রতিবেশীদের মধ্যে “পরের d1টি সবচেয়ে বড় degree-র vertex”-এর সেট S থেকে যত বেশি সম্ভব আছে। — extremal পছন্দ
- যদি N(v1) = S হয়, তাহলে G থেকে v1 মুছলেই d′ পাওয়া যায়, কাজ শেষ। না হলে কোনো x ∈ S, x ∉ N(v1), আর কোনো y ∉ S, y ∈ N(v1) আছে, যেখানে deg x ≥ deg y. — S-এর সংজ্ঞা
- y-এর v1 ছাড়া প্রতিবেশী deg y − 1 জন, যা deg x-এর চেয়ে কম; তাই x-এর এমন একজন প্রতিবেশী z আছে যে y-এর প্রতিবেশী নয় আর z ≠ y (x আর y নিজেরা যুক্ত হলে দুই পাশ থেকে y আর x বাদ দিয়ে একই তুলনা: deg x − 1 > deg y − 2). — pigeonhole ধরনের গোনা
- Edge v1y আর xz মুছে v1x আর yz যোগ করুন (2-switch). কোনো degree বদলায় না, graph simple থাকে, অথচ v1-এর S-প্রতিবেশী একজন বাড়ল: ধাপ ২-এর পছন্দের বিরোধ। তাই N(v1) = S. ∎ — contradiction
1যোগফল 14, Δ = 3 ≤ 62v1 (3) সরানো → 2,2,1,1,1,13v2 (2) সরানো → 1,1,1,1,04v5 (1) সরানো → 1,1,0,05v6 (1) সরানো → 0,0,06উল্টো পথে graph
| তালিকা | |
| কে কত | |
| নতুন edge |
- প্রাথমিক পরীক্ষা। 3 + 3 + 2 + 2 + 2 + 1 + 1 = 14, জোড়; সবচেয়ে বড় পদ 3 ≤ n − 1 = 6. শুধু এটুকু থেকে উত্তর জানা যায় না, তাই উপপাদ্য ৬.১ প্রয়োগ।
- v1 সরানো। v1-এর degree 3, তাই পরের তিনজন v2, v3, v4 থেকে 1 কমে: 2, 1, 1. বাকি v5, v6, v7 অপরিবর্তিত। নতুন তালিকা সাজালে 2, 2, 1, 1, 1, 1 (v2, v5, v3, v4, v6, v7).
- v2 সরানো। degree 2, তাই পরের দুজন v5 আর v3 থেকে 1 কমে: v5 হয় 1, v3 হয় 0. সাজালে 1, 1, 1, 1, 0.
- v5 সরানো। পরের একজন v4 থেকে 1 কমে 0. তালিকা 1, 1, 0, 0 (v6, v7, v4, v3).
- v6 সরানো। v7 থেকে 1 কমে 0. বাকি সব 0, তাই কোনো edge ছাড়াই বাস্তবায়ন সম্ভব: তালিকাটি graphical.
- Graph ফিরিয়ে আনা। প্রতিটি ধাপের edge জুড়লে v1v2, v1v3, v1v4, v2v3, v2v5, v4v5, v6v7: ৭টি edge, আর degree হুবহু 3, 3, 2, 2, 2, 1, 1. লক্ষ করুন graph-টি দুই টুকরো (v6v7 আলাদা); একই তালিকার connected বাস্তবায়নও আছে, Havel–Hakimi শুধু একটি বাস্তবায়ন দেয়।
d1 ≥ ⋯ ≥ dn ≥ 0 graphical যদি এবং কেবল যদি ∑ di জোড় আর প্রতিটি k = 1, …, n-এর জন্য
∑i=1k di ≤ k(k − 1) + ∑i=k+1n min(di, k)
প্রয়োজনীয়তার দিকটি সহজ: সবচেয়ে বড় k-টি vertex-এর degree-যোগফল তাদের নিজেদের মধ্যের edge (বড়জোর k(k − 1), কারণ প্রতিটি edge দুবার গোনা) আর বাইরের প্রতিটি vertex i-এর সঙ্গে edge (বড়জোর min(di, k)) দিয়ে সীমিত। উল্টো দিকটি কঠিন; Paul Erdős আর Tibor Gallai ১৯৬০ সালে এটি প্রকাশ করেন বলে উল্লেখ করা হয়। নিচের কোড দুটি পরীক্ষাকেই সত্যিকারের brute force-এর সঙ্গে মেলায়: n ≤ 6-এর প্রতিটি নামযুক্ত simple graph তৈরি করে তার degree sequence জমা রাখে।
from itertools import combinations, product
def havel_hakimi(seq, trace=False):
d = sorted(seq, reverse=True)
while d and d[0] > 0:
k = d.pop(0)
if k > len(d): return False
d = sorted([x - 1 for x in d[:k]] + d[k:], reverse=True)
if trace:
print(f" remove {k} -> {d}")
if d[-1] < 0:
return False
return True
def erdos_gallai(seq):
d = sorted(seq, reverse=True)
if sum(d) % 2:
return False
return all(sum(d[:k]) <= k * (k - 1) + sum(min(x, k) for x in d[k:])
for k in range(1, len(d) + 1))
for s in ([3, 3, 2, 2, 2, 1, 1], [5, 5, 4, 3, 2, 1]):
print(s, "sum", sum(s))
print(" graphical:", havel_hakimi(s, trace=True))
for n in range(1, 7): # brute force: degree sequences of all graphs
pairs = list(combinations(range(n), 2))
real = set()
for bits in product((0, 1), repeat=len(pairs)):
deg = [0] * n
for (u, v), b in zip(pairs, bits):
if b:
deg[u] += 1; deg[v] += 1
real.add(tuple(sorted(deg, reverse=True)))
cands = [s for s in product(range(n), repeat=n) if list(s) == sorted(s, reverse=True)]
hh = sum(havel_hakimi(s) == (s in real) for s in cands)
eg = sum(erdos_gallai(s) == (s in real) for s in cands)
print(f"n={n}: {len(cands):3} candidates, {len(real):3} graphical,"
f" HH agrees {hh}, EG agrees {eg}")আসল আউটপুট (ব্রাউজারের Python):
[3, 3, 2, 2, 2, 1, 1] sum 14
remove 3 -> [2, 2, 1, 1, 1, 1]
remove 2 -> [1, 1, 1, 1, 0]
remove 1 -> [1, 1, 0, 0]
remove 1 -> [0, 0, 0]
graphical: True
[5, 5, 4, 3, 2, 1] sum 20
remove 5 -> [4, 3, 2, 1, 0]
remove 4 -> [2, 1, 0, -1]
graphical: False
n=1: 1 candidates, 1 graphical, HH agrees 1, EG agrees 1
n=2: 3 candidates, 2 graphical, HH agrees 3, EG agrees 3
n=3: 10 candidates, 4 graphical, HH agrees 10, EG agrees 10
n=4: 35 candidates, 11 graphical, HH agrees 35, EG agrees 35
n=5: 126 candidates, 31 graphical, HH agrees 126, EG agrees 126
n=6: 462 candidates, 102 graphical, HH agrees 462, EG agrees 462
প্রথম trace হুবহু stepper-এর তালিকাগুলো দেয়। দ্বিতীয়টি (5, 5, 4, 3, 2, 1): যোগফল 20 জোড়, তবু দুই ধাপে একটি পদ −1 হয়ে যায়, তাই graphical নয়। সরাসরি যুক্তিও আছে: ৬টি vertex-এ degree 5 মানে বাকি সবার সঙ্গে যুক্ত; দুটি degree-5 vertex থাকলে সবার degree অন্তত 2, অথচ শেষ পদ 1. নিচের সারণিতে n = 6-এ বড় থেকে ছোট সাজানো ৪৬২টি সম্ভাব্য তালিকার মধ্যে মাত্র ১০২টি সত্যিই কোনো graph-এর degree sequence, আর Havel–Hakimi আর Erdős–Gallai দুটিই প্রতিটি তালিকায় (৪৬২-এ ৪৬২) brute force-এর সঙ্গে একমত। ১, ২, ৪, ১১, ৩১, ১০২ সংখ্যাগুলো n ≤ 6-এ graphical তালিকার সংখ্যা; একই তালিকা অনেক আলাদা graph থেকে আসতে পারে, তাই এগুলো graph-সংখ্যা নয়।
৭ · নতুন graph বানানো আর graph গোনা
- H = (W, F) হলো G = (V, E)-এর subgraph, যদি W ⊆ V আর F ⊆ E (F-এর প্রতিটি edge-এর দুই প্রান্ত W-তে)।
- W ⊆ V-এর induced subgraph G[W]: vertex W, আর E-এর যেসব edge-এর দুই প্রান্তই W-তে, তাদের সবগুলো.
- Simple graph G-এর complement Ḡ: একই V, আর uv একটি edge ঠিক তখন, যখন u ≠ v আর uv ∉ E. অর্থাৎ Ḡ-এর edge = Kn-এর edge − E (পর্ব ১৫-এর complement, universal set Kn-এর edge).
- G1 = (V1, E1) আর G2 = (V2, E2)-এর union: (V1 ∪ V2, E1 ∪ E2).
পার্থক্যটি মনে রাখার উপায়: subgraph-এ যেকোনো edge ফেলে দেওয়া যায়, induced subgraph-এ যায় না। হাব-graph-এ W = {D, G, T} নিলে G[W] একটি ত্রিভুজ (DG, DT, GT), আর শুধু {DG, DT} নিয়ে বানানো graph একটি subgraph যা induced নয়। Complement-এ প্রতিটি vertex-এর degree n − 1 − deg(v), কারণ বাকি n − 1 জনের মধ্যে যারা G-এ প্রতিবেশী নয়, তারাই Ḡ-এ প্রতিবেশী। হাব-graph-এর complement-এ 15 − 8 = 7টি edge আর degree (0, 3, 2, 3, 3, 3) (ক্রম D, G, N, S, T, M): D সবার সঙ্গে যুক্ত বলে Ḡ-এ একা।
নির্দিষ্ট n-টি vertex {1, 2, …, n}-এর ওপর আলাদা simple graph-এর সংখ্যা 2C(n,2), আর ঠিক m-টি edge-যুক্ত graph-এর সংখ্যা C(C(n, 2), m).
- Vertex সেট নির্দিষ্ট, তাই একটি simple graph পুরোপুরি তার edge-সেট E দিয়ে নির্ধারিত, আর E হলো সম্ভাব্য C(n, 2)টি জোড়ার সেটের একটি subset. — সংজ্ঞা ১.১
- উল্টো দিকে, সেই জোড়াগুলোর প্রতিটি subset একটি simple graph দেয়। তাই graph ↔ subset একটি bijection (পর্ব ১৬)। — দুই দিকের রূপান্তর
- C(n, 2)-উপাদানের সেটের subset 2C(n,2)টি, আর ঠিক m-উপাদানের subset C(C(n, 2), m)টি (পর্ব ৩৩)। ∎ — bijection আকার রক্ষা করে
৫টি vertex-এ তাই 210 = 1024টি graph, আর ঠিক ৪টি edge-এর C(10, 4) = 210টি। “নামযুক্ত” (labelled) শব্দটি জরুরি: vertex-এর নাম ভুলে গিয়ে শুধু আকৃতি গুনলে ৪টি vertex-এ মাত্র ১১টি আলাদা graph, যা পর্ব ৫১-এ Burnside দিয়ে গোনা হয়েছে, আর “একই আকৃতি”-র নির্ভুল সংজ্ঞা graph isomorphism, পর্ব ৫৮-এর বিষয়।
নিচের কোড n ≤ 6-এর প্রতিটি নামযুক্ত graph তৈরি করে তিনটি জিনিস গোনে: মোট সংখ্যা (2C(n,2)-এর সঙ্গে তুলনা), প্রতিটি k-এর জন্য k-regular graph (উপপাদ্য ৪.১), আর যেসব graph-এ কোনো isolated vertex নেই (δ ≥ 1) তাদের মধ্যে কয়টি এক টুকরো নয়, যা §৮-এর ভুল প্রমাণের জন্য লাগবে। “connected” মানে যেকোনো দুটি vertex-এর মধ্যে path আছে; বিস্তারিত পর্ব ৫৯-এ।
from itertools import combinations, product
from collections import Counter
from math import comb
def connected(n, edges):
adj = {v: [] for v in range(n)}
for u, v in edges:
adj[u].append(v); adj[v].append(u)
seen, stack = {0}, [0]
while stack:
for w in adj[stack.pop()]:
if w not in seen:
seen.add(w); stack.append(w)
return len(seen) == n
print(" n graphs 2^C(n,2) k-regular for k = 0..n-1 min deg>=1 disconnected")
for n in range(1, 7):
pairs = list(combinations(range(n), 2))
total, reg, pos, bad = 0, Counter(), 0, 0
for bits in product((0, 1), repeat=len(pairs)):
E = [p for p, b in zip(pairs, bits) if b]
deg = [0] * n
for u, v in E:
deg[u] += 1; deg[v] += 1
total += 1
if len(set(deg)) == 1:
reg[deg[0]] += 1
if min(deg) >= 1:
pos += 1
bad += not connected(n, E)
print(f"{n:2} {total:7} {2 ** comb(n, 2):9} {[reg[k] for k in range(n)]!s:26}"
f" {pos:10} {bad:12}")আসল আউটপুট (ব্রাউজারের Python):
n graphs 2^C(n,2) k-regular for k = 0..n-1 min deg>=1 disconnected
1 1 1 [1] 0 0
2 2 2 [1, 1] 1 0
3 8 8 [1, 0, 1] 4 0
4 64 64 [1, 3, 3, 1] 41 3
5 1024 1024 [1, 0, 12, 0, 1] 768 40
6 32768 32768 [1, 15, 70, 70, 15, 1] 27449 745
দ্বিতীয় আর তৃতীয় কলাম প্রতিটি সারিতে সমান: উপপাদ্য ৭.২. regular কলামে n = 5-এ k = 1 আর k = 3-এর ঘরে 0, কারণ 5 × 1 আর 5 × 3 বিজোড়; বাকি সব ঘর ধনাত্মক, ঠিক উপপাদ্য ৪.১-এর মতো। n = 4-এ 1-regular graph ৩টি (চারজনকে দুই জোড়ায় ভাগ করার উপায়), আর 2-regular ৩টি (৪টি vertex-এর cycle). প্রতিটি সারি প্রতিসম, কারণ complement নিলে k-regular graph (n − 1 − k)-regular হয়, আর G ↦ Ḡ একটি bijection. শেষ কলামটি পরের অংশে কাজে লাগবে: n = 4-এ δ ≥ 1-এর ৪১টি graph-এর ৩টি এক টুকরো নয়।
৮ · প্রয়োগ, পরীক্ষার অঙ্ক আর একটি ভুল প্রমাণ
কোথায় কোথায় graph
- সামাজিক নেটওয়ার্ক: মানুষ vertex, বন্ধুত্ব edge (undirected), আর “অনুসরণ করা” তীর (directed). degree মানে বন্ধুর সংখ্যা।
- ওয়েব: পাতা vertex, লিংক তীর; in-degree বেশি মানে অনেক পাতা এই পাতাকে দেখায়, যা সার্চ ইঞ্জিনের পুরোনো একটি সংকেত হিসেবে পরিচিত।
- রাস্তা আর ডেলিভারি: বাজারঘরের মতো হাব আর রুট; একমুখী রাস্তা থাকলে directed, একাধিক বিকল্প রাস্তা থাকলে multigraph.
- অণুর মডেল: রসায়নে পরমাণু vertex আর রাসায়নিক বন্ধন edge হিসেবে আঁকা হয়; এক-বন্ধনের সরল ক্ষেত্রে একটি পরমাণুর degree তার যোজ্যতার সঙ্গে মেলে (যেমন কার্বন 4), আর দ্বিবন্ধন parallel edge হিসেবে আঁকলে graph-টি multigraph হয়। এটি একটি সরলীকৃত মডেল; বাস্তব রসায়নের সব খুঁটিনাটি এতে আসে না।
অঙ্ক ১: Handshake দিয়ে vertex গোনা
একটি simple graph-এ ১৫টি edge; তিনটি vertex-এর degree 4, বাকি সবার 3. vertex কয়টি? এমন graph কি সত্যিই আছে?
- n-টি vertex ধরলে ∑ deg = 3 · 4 + (n − 3) · 3 = 2 · 15 = 30.
- 12 + 3n − 9 = 30, তাই 3n = 27, n = 9.
- অস্তিত্ব: তালিকা (4, 4, 4, 3, 3, 3, 3, 3, 3)-এ Havel–Hakimi চালালে সব পদ 0-তে পৌঁছায়, তাই আছে (scratch-এ যাচাই করা)।
অঙ্ক ২: edge গোনা
Q4, K3,4 আর W6-এ কয়টি edge? উত্তর: Q4-এ 4 · 23 = 32; K3,4-এ 3 · 4 = 12; W6-এ রিমে ৬টি আর hub থেকে ৬টি, মোট 12, যা handshake দিয়েও মেলে: (6 · 3 + 6)/2 = 12.
অঙ্ক ৩: Bipartite কি না
C7, Q3, K2,3 আর K4-এর কোনগুলো bipartite? C7 নিজেই একটি odd cycle, তাই নয়; K4-এ ত্রিভুজ আছে, তাই নয়; Q3 (1-এর সংখ্যার parity) আর K2,3 (সংজ্ঞা অনুযায়ী) bipartite.
প্রমাণের ভুল ধরুন: graph-এ induction-এর ফাঁদ
একজন লিখলেন: “দাবি: n ≥ 2 vertex-এর যে simple graph-এ কোনো isolated vertex নেই (δ ≥ 1), সেটি connected. প্রমাণ (n-এর ওপর induction): n = 2-এ δ ≥ 1 মানে একমাত্র edge-টি আছে, graph connected. এখন ধরুন n-vertex-এর জন্য সত্য। δ ≥ 1-এর একটি n-vertex graph G নিন; induction hypothesis অনুযায়ী G connected. একটি নতুন vertex v যোগ করে তাকে G-এর অন্তত একটি vertex-এর সঙ্গে যুক্ত করুন; নতুন graph-এও δ ≥ 1, আর v পুরোনো connected অংশে যুক্ত বলে নতুন graph connected. তাই দাবিটি সব n-এর জন্য সত্য।”
ভুল কোথায়: Inductive step-কে প্রমাণ করতে হয় যে প্রতিটি (n + 1)-vertex graph যার δ ≥ 1, সেটি connected. এখানে উল্টো পথে হাঁটা হয়েছে: একটি ছোট graph থেকে “বানানো” কিছু বড় graph দেখা হয়েছে। কিন্তু সব বড় graph এভাবে আসে না। পাল্টা-উদাহরণ: n = 4-এ দুটি আলাদা edge {12, 34}. এর যেকোনো vertex মুছলে একটি isolated vertex থাকে, তাই এটি “δ ≥ 1-এর ৩-vertex graph + একটি নতুন vertex” হিসেবে কখনো তৈরি হয় না, আর এটি connected-ও নয়। §৭-এর কোডের শেষ কলাম দেখায় এমন graph n = 4-এ ৩টি, n = 5-এ ৪০টি, n = 6-এ ৭৪৫টি; দাবিটি শুধু n = 2 আর 3-এ সত্য। সঠিক পদ্ধতি (“shrink down, grow back”): যেকোনো (n + 1)-vertex graph নিয়ে শুরু করুন, একটি vertex মুছে দেখান যে ছোট graph-টি hypothesis-এর শর্ত মানে, তারপর induction hypothesis প্রয়োগ করে মুছে ফেলা vertex ফিরিয়ে আনুন। এখানে প্রথম ধাপেই আটকে যায়, আর আটকে যাওয়াই সংকেত যে দাবিটি মিথ্যা। Graph-এর ওপর induction-এর এই ফাঁদ পর্ব ১১-এর strong induction-এর ক্ষেত্রেও একই।
আরও গভীরে: এলোমেলো graph-এর গণিতে (Erdős আর Rényi, ১৯৫৯–৬০) প্রতিটি জোড়া স্বাধীনভাবে p সম্ভাবনায় edge পায়; তখন degree প্রায় binomial বণ্টন মানে, আর p ধীরে বাড়ালে হঠাৎ একটি বিশাল connected অংশ জন্ম নেয়, যা পর্ব ৪৩-এর পদ্ধতির স্বাভাবিক বিস্তার। বাস্তব নেটওয়ার্কের degree sequence প্রায়ই খুব অসম (অল্প কয়েকটি vertex-এর degree বিশাল), তাই network science-এ একটি নির্দিষ্ট degree sequence রেখে এলোমেলো graph বানানোর “configuration model” তুলনার মাপকাঠি হিসেবে ব্যবহার হয়। Havel–Hakimi-র প্রমাণের 2-switch ধাপটিই এমন graph এলোমেলোভাবে বদলানোর একটি প্রচলিত কৌশল, কারণ এতে degree sequence অপরিবর্তিত থাকে।
পরীক্ষা ও ইন্টারভিউতে: বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় এই ধরনের প্রশ্ন প্রায়ই আসে:
- কোনো পার্টিতে কি ৯ জনের প্রত্যেকে ঠিক ৩ জনের সঙ্গে হাত মেলাতে পারেন? না; 9 × 3 = 27 বিজোড়, handshake ভাঙে।
- degree 1, 2, 3, 4, 5-এর simple graph আছে কি? না; যোগফল 15 বিজোড়।
- Kn-এ edge কয়টি, আর Kn কখন bipartite? n(n − 1)/2; শুধু n ≤ 2 হলে।
- একটি graph bipartite কি না কীভাবে দেখবেন? BFS দিয়ে দুই রং; একই রঙের edge পেলে odd cycle, তাই নয়।
- Qn-এ edge কয়টি? n · 2n−1, কারণ 2nটি vertex-এর প্রত্যেকের degree n.
৯ · AI-এর যুগে — graph-এর প্রমাণ আর হিসাব যাচাই
Graph-এর প্রশ্নে AI সহকারী সংজ্ঞা সাধারণত ঠিক লেখে, কিন্তু কোন ধরনের graph-এর কথা হচ্ছে তা গুলিয়ে ফেলে, আর induction-এর প্রমাণে আত্মবিশ্বাসী ভুল করে। কয়েকটি নিয়মিত ভুল আর ধরার উপায়:
| AI-এর ভুল | কীভাবে ধরবেন |
|---|---|
| Loop-কে degree-তে একবার গোনা, বা directed graph-এ in-degree-র যোগফল 2|E| বলা | একটি loop বা একটি তীরের ছোট উদাহরণে দুই দিক গুনে দেখুন |
| “যোগফল জোড়, তাই graphical” বলা | (3, 3, 3, 1) দিয়ে পরীক্ষা করুন, Havel–Hakimi চালান |
| Havel–Hakimi-র প্রতি ধাপে নতুন করে সাজাতে ভুলে যাওয়া | ছোট তালিকা নিজে হাতে চালিয়ে brute force-এর সঙ্গে মেলান |
| “odd cycle নেই ⇒ bipartite” প্রমাণে শুধু connected graph ধরে অন্য অংশ ভুলে যাওয়া | প্রমাণে component-এ ভাগের ধাপটি খুঁজুন |
| ছোট graph থেকে বড় graph “বানিয়ে” induction | যুক্তিটি কি প্রতিটি বড় graph ঢাকে? δ ≥ 1-এর মতো পাল্টা-উদাহরণ খুঁজুন |
| Wn-এর vertex-সংখ্যা বা Km,n-এর edge ভুল | সংজ্ঞা লিখে n = 3 বা 4-এ ছবি এঁকে গুনুন |
AI-এর কাছে graph-এর প্রমাণ বা হিসাব চাইলে এমন কাঠামো দিন, যাতে প্রতিটি ধাপ আলাদা করে যাচাই করা যায়:
AI-এর উত্তর হাতে পেলে — যাচাইয়ের চেকলিস্ট
Graph-এর সুবিধা হলো ছোট ক্ষেত্রে সবকিছু গোনা যায়: ৬টি vertex-এ মাত্র ৩২,৭৬৮টি graph, যা ব্রাউজারেই এক মুহূর্তে পরীক্ষা হয়। ছোট ক্ষেত্রে টিকে গেলেই দাবি সত্য হয় না, কিন্তু ভুল দাবি প্রায়ই ৪ বা ৫টি vertex-এই ধরা পড়ে। তাই আগে পাল্টা-উদাহরণ খুঁজুন, তারপর প্রমাণে ভরসা করুন।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।
প্র ০১Graph তত্ত্বের শুরু কোথায়? Euler-এর সেতু-সমস্যা থেকে আধুনিক “graph” শব্দ পর্যন্ত ইতিহাসটি কেমন?
সাধারণভাবে বলা হয়, graph তত্ত্বের জন্ম ১৭৩৬ সালে, যখন Leonhard Euler Königsberg শহরের (আজকের Kaliningrad) সাতটি সেতুর ধাঁধা নিয়ে লেখেন: সব সেতু ঠিক একবার পার হয়ে কি শহর ঘোরা যায়? Euler-এর আসল অন্তর্দৃষ্টি ছিল এই পর্বের সংজ্ঞা ১.১-এর মূল কথা: শহরের আকৃতি, সেতুর দৈর্ঘ্য, রাস্তার বাঁক, সব অপ্রাসঙ্গিক; প্রাসঙ্গিক শুধু কোন ভূখণ্ড কোনটির সঙ্গে কতগুলো সেতু দিয়ে যুক্ত। আধুনিক ভাষায় ভূখণ্ড vertex আর সেতু edge, আর যেহেতু একই দুই ভূখণ্ডের মধ্যে একাধিক সেতু ছিল, graph-টি আসলে একটি multigraph. Euler-এর উত্তর degree-র parity-র ওপর দাঁড়িয়ে, যা এই পর্বের handshake যুক্তির খুব কাছের; পুরো উপপাদ্য আর প্রমাণ পর্ব ৬০ “Euler আর Hamilton path”-এ আসবে। উল্লেখ্য, Euler-এর মূল লেখায় আজকের মতো বিন্দু-দাগের ছবি ছিল না বলে ইতিহাসবিদেরা উল্লেখ করেন; ছবিটি পরের যুগের পাঠ্যবইয়ের সংযোজন।
উনিশ শতকে graph নানা দিক থেকে ফিরে আসে। Gustav Kirchhoff বৈদ্যুতিক বর্তনী বিশ্লেষণে (১৮৪০-এর দশক) tree-এর ধারণা ব্যবহার করেন, Arthur Cayley রসায়নের অণুর গঠন গুনতে tree গোনেন, আর “graph” শব্দটি James Joseph Sylvester ১৮৭৮ সালে রসায়নের “graphic notation” থেকে ধার করে চালু করেন বলে সাধারণত উল্লেখ করা হয়। চার রঙের সমস্যা (১৮৫২) পরের শতাব্দী জুড়ে গবেষণাকে টেনে নিয়ে যায় (পর্ব ৬৩)।
বিষয়টি স্বতন্ত্র শাখা হিসেবে প্রতিষ্ঠা পায় বিশ শতকে। Dénes Kőnig-এর ১৯৩৬ সালের বইটিকে graph তত্ত্বের প্রথম পাঠ্যবই হিসেবে ধরা হয়। এরপর কম্পিউটার আসায় graph হয়ে ওঠে নেটওয়ার্ক, সূচি, সার্কিট আর ডেটাবেসের সাধারণ ভাষা; DSA কোর্সের পর্ব ৩৯ থেকে graph algorithm-এর পুরো একটি মডিউল এই ভাষার ওপর দাঁড়িয়ে।
মূল উপলব্ধি: Graph তত্ত্বের প্রথম পদক্ষেপই ছিল বিমূর্তকরণ: আকৃতি ভুলে শুধু সংযোগ রাখা। তাই একই গণিত শহরের সেতু, অণু, বর্তনী আর ইন্টারনেটে একসঙ্গে কাজ করে।
প্র ০২“আপনার বন্ধুদের গড় বন্ধু-সংখ্যা আপনার চেয়ে বেশি” — friendship paradox কী, আর degree-র গণিত দিয়ে এটি কেন প্রায় সবসময় সত্য?
সমাজবিজ্ঞানী Scott Feld ১৯৯১ সালের একটি প্রবন্ধে একটি অদ্ভুত পর্যবেক্ষণ তুলে ধরেন বলে পরিচিত: বেশিরভাগ মানুষের বন্ধুদের গড় বন্ধু-সংখ্যা তাঁদের নিজেদের বন্ধু-সংখ্যার চেয়ে বেশি। এটি মানুষের মনস্তত্ত্ব নয়, degree-র গণিত। কারণটি হলো, “একজন এলোমেলো বন্ধু” বাছাই করলে বেশি বন্ধুওয়ালা মানুষ বেশিবার বাছাই হন: degree d-এর একজন মানুষ d জনের বন্ধু-তালিকায় আছেন।
গণিতে লিখি। n জন মানুষ, m-টি বন্ধুত্ব, গড় degree μ = 2m/n (handshake). প্রতিটি বন্ধুত্ব uv-এর দুই প্রান্ত থেকে “বন্ধুর degree” দেখলে মোট যোগফল ∑v deg(v) · deg(v) = ∑ deg(v)2, কারণ v নিজের deg(v)জন বন্ধুর তালিকায় প্রত্যেকবার deg(v) সংখ্যা নিয়ে আসে। তাই “বন্ধুর গড় degree” = ∑ deg(v)2 / 2m = μ + σ2/μ, যেখানে σ2 degree-র variance (পর্ব ৪১-এর ভাষায়)। variance কখনো ঋণাত্মক নয়, তাই বন্ধুর গড় degree ≥ গড় degree, আর সমতা শুধু যখন সবার degree সমান (regular graph).
এই পর্বের হাব-graph-এ দেখুন: গড় degree 16/6 ≈ 2.67, কিন্তু প্রতিটি রুটের দুই প্রান্ত থেকে প্রতিবেশীর degree গড় করলে 50/16 = 3.125 (scratch-এ গুনে মেলানো)। কারণ D-এর degree 5, আর সে ৫ জনের প্রতিবেশী-তালিকায় আছে। বাস্তব সামাজিক নেটওয়ার্কে degree-র বৈষম্য বিশাল, তাই পার্থক্যও বড়।
এর একটি ব্যবহারিক প্রয়োগ নিয়ে আলোচনা হয়েছে: সংক্রামক রোগের প্রাথমিক সংকেত পেতে এলোমেলো মানুষের বদলে “এলোমেলো মানুষের বন্ধুদের” নজরে রাখা, কারণ তাঁরা গড়ে বেশি সংযুক্ত। একই যুক্তি নমুনা জরিপে সতর্ক করে: “বন্ধুর মাধ্যমে” পাওয়া নমুনা বেশি সংযুক্ত মানুষের দিকে ঝুঁকে থাকে।
মূল উপলব্ধি: Degree অসম হলে “এলোমেলো edge-এর প্রান্ত” আর “এলোমেলো vertex” এক জিনিস নয়; handshake আর variance মিলে দেখায় বন্ধুদের গড় degree কখনো আপনার গড়ের কম নয়।
প্র ০৩Degree sequence থেকে graph কতটা বোঝা যায়? একই তালিকার দুটি graph কতটা আলাদা হতে পারে, আর বাস্তবে এই প্রশ্ন কোথায় আসে?
Degree sequence একটি সংক্ষিপ্তসার, আর সংক্ষিপ্তসারে তথ্য হারায়। সবচেয়ে সরল উদাহরণ: (2, 2, 2, 2, 2, 2) তালিকাটি C6 থেকেও আসে, দুটি আলাদা ত্রিভুজ থেকেও আসে। প্রথমটি connected আর bipartite, দ্বিতীয়টি দুই টুকরো আর তাতে odd cycle আছে। অর্থাৎ degree sequence দেখে connectedness বা bipartiteness বলা যায় না। Havel–Hakimi-র stepper-এও এটি দেখা গেছে: algorithm-টি একটি দুই-টুকরো graph দিয়েছিল, যদিও একই তালিকার connected graph-ও আছে।
উল্টো দিকে, কিছু তথ্য degree sequence থেকে সরাসরি আসে: edge-সংখ্যা (handshake), regular কি না, isolated vertex আছে কি না, আর কিছু ক্ষেত্রে পুরো graph. যেমন (n − 1, 1, 1, …, 1) শুধু একটি “তারা” (star) দিয়েই সম্ভব। যে graph তার degree sequence থেকেই (নাম বাদে) পুরো নির্ধারিত, তাদের নিয়ে আলাদা গবেষণা আছে। আর দুটি graph “একই আকৃতি” কি না (isomorphism) যাচাইয়ে degree sequence হলো প্রথম ছাঁকনি: তালিকা আলাদা হলে isomorphic নয়, তালিকা এক হলে আরও পরীক্ষা লাগে (পর্ব ৫৮)।
বাস্তবে এই প্রশ্ন আসে network science-এ। ধরুন একটি সামাজিক নেটওয়ার্কে অনেক ত্রিভুজ (বন্ধুর বন্ধু আমার বন্ধু) দেখা গেল। এটি কি বিশেষ কিছু, নাকি শুধু degree-গুলোর স্বাভাবিক ফল? উত্তর পেতে একই degree sequence রেখে অনেকগুলো এলোমেলো graph বানিয়ে তাদের ত্রিভুজ-সংখ্যার সঙ্গে তুলনা করা হয়। এলোমেলো graph বানানোর একটি প্রচলিত উপায় Havel–Hakimi-র প্রমাণের 2-switch: দুটি edge ab, cd মুছে ac, bd যোগ করা, যা degree অপরিবর্তিত রাখে। জানা ফলাফল আছে যে একই degree sequence-এর যেকোনো দুটি simple graph-কে 2-switch-এর একটি শৃঙ্খল দিয়ে একটি থেকে অন্যটিতে নেওয়া যায়, যা Havel–Hakimi-র প্রমাণের যুক্তি থেকেই আসে।
Erdős–Gallai (১৯৬০) একটি সম্পূর্ণ বৈশিষ্ট্য দেয়, আর তাতে n-টি অসমতা; পরে দেখানো হয়েছে যে সব অসমতা পরীক্ষার দরকার নেই, কিছু বিশেষ k-তেই যথেষ্ট, যা বড় তালিকায় সময় বাঁচায় বলে উল্লেখ করা হয়।
মূল উপলব্ধি: Degree sequence edge-সংখ্যা আর regular-তার মতো তথ্য দেয়, কিন্তু connectedness বা bipartiteness দেয় না; একই তালিকার graph-গুলো 2-switch দিয়ে পরস্পর যুক্ত, যা network science-এর তুলনামূলক মডেলের ভিত্তি।
প্র ০৪Bipartite graph বাস্তবে কোথায় আসে, আর দুই রঙের প্রশ্ন সহজ অথচ তিন রঙের প্রশ্ন কঠিন কেন?
দুই ধরনের বস্তু আর তাদের মধ্যের সম্পর্ক থাকলেই bipartite graph: কর্মী আর শিফট, ক্রেতা আর পণ্য (কে কী কিনেছেন), শিক্ষার্থী আর বিষয়, লেখক আর প্রবন্ধ। সুপারিশ-ব্যবস্থার (recommendation system) গোড়ার ডেটা প্রায়ই এমন একটি ক্রেতা-পণ্য graph. Hungarian গণিতবিদ Dénes Kőnig বিশ শতকের প্রথম দিকে bipartite graph-এর matching নিয়ে মৌলিক ফলাফল প্রমাণ করেন বলে জানা যায় (König-এর উপপাদ্য, পর্ব ৬৪)।
দুই রঙের প্রশ্নটি সহজ, কারণ একটি vertex-এর রং ঠিক করলে তার প্রতিবেশীর রং বাধ্যতামূলক হয়ে যায়; কোনো পছন্দ থাকে না। BFS শুধু এই বাধ্যবাধকতা ছড়িয়ে দেয়, আর কোথাও বিরোধ হলে উপপাদ্য ৫.২-এর প্রমাণ সেই বিরোধকে একটি odd cycle-এ রূপ দেয়। তাই সময় লাগে vertex আর edge-সংখ্যার যোগফলের মাপে। তিন রঙে কিন্তু একটি vertex-এর রং ঠিক করলেও প্রতিবেশীর দুটি বিকল্প থাকে, আর বিকল্পগুলো জমে গিয়ে সম্ভাবনা exponential হারে বাড়ে। Richard Karp ১৯৭২ সালের বিখ্যাত তালিকায় graph colouring-কে NP-complete সমস্যার মধ্যে রাখেন বলে উল্লেখ করা হয়, আর 3-colouring-ও NP-complete বলে প্রমাণিত (DSA কোর্সের পর্ব ৬৪)। অর্থাৎ ২ থেকে ৩-এ যাওয়া মানে “সহজ” থেকে “সম্ভবত কঠিন”-এ লাফ।
আরেকটি সূক্ষ্ম শিক্ষা হলো certificate. Bipartite প্রশ্নে “হ্যাঁ” আর “না” দুটি উত্তরেরই ছোট, সহজে যাচাইযোগ্য প্রমাণপত্র আছে (একটি রং-বিন্যাস, বা একটি odd cycle). 3-colouring-এ “হ্যাঁ”-এর প্রমাণপত্র সহজ (রং-বিন্যাস), কিন্তু “না”-এর জন্য কোনো ছোট প্রমাণপত্র সাধারণভাবে জানা নেই। সফটওয়্যার প্রকৌশলে “certifying algorithm” ধারণাটি ঠিক এটি চায়: উত্তরের সঙ্গে এমন সাক্ষ্য দেওয়া, যা একটি সরল checker যাচাই করতে পারে, যাতে algorithm-এর কোডে লুকোনো bug ধরা পড়ে।
মূল উপলব্ধি: দুই রঙে প্রতিটি সিদ্ধান্ত বাধ্যতামূলক বলে BFS-ই যথেষ্ট, আর দুই দিকের উত্তরেরই সাক্ষ্য আছে; তিন রঙে পছন্দের বিস্ফোরণ সমস্যাটিকে NP-complete করে।
প্র ০৫2C(n,2) কত বড়, আর “প্রায় সব graph”-এর আচরণ নিয়ে গণিতবিদেরা কী জানেন?
নামযুক্ত graph-এর সংখ্যা বিস্ফোরকভাবে বাড়ে: n = 4-এ 64, n = 6-এ 32,768, n = 10-এ 245 (প্রায় ৩৫ লক্ষ কোটি), আর n = 20-এ 2190. তাই এই পর্বের brute force n ≤ 6-এ আরামে চলে, n = 8-এ (228, প্রায় ২৭ কোটি) ব্রাউজারে কষ্টকর হয়ে যায়, আর তার পরে অসম্ভব। নাম ভুলে আকৃতি গুনলে সংখ্যা কমে, কিন্তু খুব বেশি নয়: n-টি vertex-এর নাম বদলানোর উপায় n!টি, তাই আকৃতি-সংখ্যা অন্তত 2C(n,2)/n!, আর বড় n-এ প্রায় এর সমানই, কারণ “প্রায় সব” graph-এর কোনো অ-তুচ্ছ symmetry নেই। এই ফলাফলের সঙ্গে Erdős আর Rényi-এর ১৯৬৩ সালের কাজ যুক্ত বলে উল্লেখ করা হয়; graph গোনার symmetry-ভিত্তিক পদ্ধতি পর্ব ৫১-এ।
“প্রায় সব graph” কথাটির অর্থ: প্রতিটি জোড়ায় মুদ্রা ছুড়ে edge বসালে একটি এলোমেলো graph পাওয়া যায়, আর কোনো ধর্মের সম্ভাবনা n বাড়ার সঙ্গে 1-এর দিকে গেলে বলা হয় প্রায় সব graph-এর সেই ধর্ম আছে। যেমন প্রায় সব graph connected, তাদের ব্যাস (diameter) মাত্র 2, আর প্রায় সব graph bipartite নয় (ত্রিভুজ থাকা প্রায় নিশ্চিত)। এই ধাঁচের যুক্তিই পর্ব ৪৩-এর probabilistic method: কোনো ধর্মের graph-এর অস্তিত্ব প্রমাণে দেখানো যে এলোমেলো graph-এ ধর্মটি ধনাত্মক সম্ভাবনায় থাকে।
এই গণনার সঙ্গে Ramsey তত্ত্বের একটি সুন্দর টান আছে। পর্ব ৩২-এ প্রমাণিত R(3, 3) = 6 বলে: ৬ জন মানুষের মধ্যে সবসময় ৩ জন পরস্পর বন্ধু বা ৩ জন পরস্পর অপরিচিত, অর্থাৎ ৬-vertex-এর প্রতিটি graph-এ, বা তার complement-এ, একটি ত্রিভুজ আছে। এই পর্বের complement-এর ভাষায় কথাটি আবার পড়ুন: 215 = 32,768টি graph-এর প্রতিটিতে হয় G, নয় Ḡ-এ ত্রিভুজ। এত বড় সংখ্যক graph-এর কোনো ব্যতিক্রম নেই, এটিই এমন উপপাদ্যের শক্তি।
মূল উপলব্ধি: নামযুক্ত graph 2C(n,2)টি, যা brute force-কে n ≈ 7-এর মধ্যে আটকে রাখে; বড় n-এ প্রমাণ আর সম্ভাবনার যুক্তিই একমাত্র পথ, আর সেই যুক্তি বলে “প্রায় সব” graph connected আর symmetry-হীন।
অনুশীলন
আগে খাতায় করুন, তারপর উত্তর খুলে মেলান।
-
প্রমাণ: n ≥ 2 vertex-এর যেকোনো simple graph-এ অন্তত দুটি vertex-এর degree সমান। প্রমাণ করুন, আর দেখান যে simple শর্তটি বাদ দিলে (multigraph-এ) দাবিটি মিথ্যা হতে পারে।
- Simple graph-এ প্রতিটি degree 0, 1, …, n − 1-এর একটি: বাকি n − 1 জনের বেশি প্রতিবেশী সম্ভব নয়। — সংজ্ঞা ১.১
- 0 আর n − 1 একসঙ্গে থাকতে পারে না: কারও degree n − 1 হলে সে সবার সঙ্গে যুক্ত, তাই কারও degree 0 নয়। — বিরোধ
- তাই n-টি degree আসলে n − 1টি মানের মধ্যে পড়ে ({0, …, n − 2} বা {1, …, n − 1})। — ধাপ ১, ২
- পর্ব ৩২-এর pigeonhole principle অনুযায়ী অন্তত দুটি vertex-এর degree সমান। ∎ — pigeonhole
Multigraph-এ দাবিটি ভাঙে: দুটি vertex a, b-এর মধ্যে ২টি parallel edge আর b, c-এর মধ্যে ১টি edge নিলে degree a 2, b 3, c 1, সব আলাদা। ধাপ ১-এর “বড়জোর n − 1” সীমাটি parallel edge থাকলে আর খাটে না। (বাজারঘরের ভাষায়: যেকোনো হাব-নেটওয়ার্কে, যেখানে দুটি হাবের মধ্যে বড়জোর একটি রুট, অন্তত দুটি হাবের রুট-সংখ্যা সমান।)
-
হিসাব: (ক) একটি 4-regular simple graph-এ ২০টি edge; vertex কয়টি? (খ) (4, 4, 4, 3, 2, 1) কি graphical? Havel–Hakimi দিয়ে দেখান। (গ) ৫টি নামযুক্ত vertex-এ ঠিক ৪টি edge-এর simple graph কয়টি? (ঘ) Q5-এ কয়টি edge?
(ক) 4n = 2 · 20, তাই n = 10; উপপাদ্য ৪.১ অনুযায়ী এমন graph আছে (4 জোড়, 4 ≤ 9).
(খ) যোগফল 18, জোড়। 4 সরিয়ে পরের চারটি থেকে 1 কমান: 3, 3, 2, 1, 1. 3 সরিয়ে: 2, 1, 0, 1 → সাজালে 2, 1, 1, 0. 2 সরিয়ে: 0, 0, 0. সব 0, তাই graphical (প্রথম ধাপের আগের তালিকা 4, 4, 3, 2, 1 থেকেই শুরু, কারণ প্রথম 4 বাদ পড়েছে; scratch-এ Havel–Hakimi কোড দিয়ে মেলানো)।
(গ) C(10, 4) = 210 (উপপাদ্য ৭.২)।
(ঘ) 5 · 24 = 80.
-
আউটপুট অনুমান: কোড না চালিয়ে বলুন কী ছাপা হবে, আর কেন। তারপর যেকোনো Python-এ চালিয়ে মেলান।
from collections import Counter edges = [("D", "G"), ("D", "G"), ("G", "G"), ("G", "T")] deg = Counter() for u, v in edges: deg[u] += 1; deg[v] += 1 print(dict(deg), sum(deg.values()), len(edges)){'D': 2, 'G': 5, 'T': 1} 8 4Graph-টি একটি pseudograph: D আর G-এর মধ্যে দুটি parallel edge, G-তে একটি loop, আর GT. D পায় 2. G পায় parallel edge থেকে 2, loop থেকে 2 (কারণ u আর v দুটিই "G", তাই একই লাইনে দুবার 1 যোগ হয়), আর GT থেকে 1: মোট 5. T পায় 1. যোগফল 8 = 2 × 4, handshake ঠিক আছে, আর বিজোড় vertex G আর T, দুজন। কোডটি loop-কে স্বয়ংক্রিয়ভাবে দুবার গোনে, সংজ্ঞা ২.১-এর মতোই। আউটপুট CPython 3.14-এ চালিয়ে মেলানো।
-
প্রমাণের ভুল ধরুন: একজন লিখলেন: “যে simple graph-এ সব degree অন্তত 2, সেটি একটি cycle. প্রমাণ: যেকোনো vertex v0 থেকে হাঁটা শুরু করুন; প্রতিটি vertex-এ অন্তত দুটি edge, তাই যে edge দিয়ে ঢুকেছেন তা ছাড়া অন্য একটি দিয়ে বের হওয়া যায়। vertex সসীম, তাই একসময় আগে দেখা কোনো vertex-এ ফিরবেন, আর একটি cycle তৈরি হয়। তাই graph-টি একটি cycle.” ভুলটি কোথায়? সবচেয়ে ছোট পাল্টা-উদাহরণ দিন, আর সঠিক দাবিটি লিখুন।
- যা প্রমাণ হয়েছে: যুক্তিটি দেখায় graph-এ একটি cycle আছে (সসীম হাঁটায় পুনরাবৃত্তি, আর প্রথম পুনরাবৃত্তি থেকে একটি cycle). এটি সঠিক এবং পরিচিত ফল: δ ≥ 2 হলে graph-এ cycle থাকে।
- ভুল লাফ: “একটি cycle আছে” থেকে “graph-টি নিজেই একটি cycle” সিদ্ধান্ত। পাওয়া cycle-এর বাইরে আরও vertex বা edge থাকতে পারে।
- পাল্টা-উদাহরণ: ৪টি vertex-এ diamond (C4 আর একটি কর্ণ): degree 3, 2, 3, 2, সব ≥ 2, কিন্তু ৫টি edge, অথচ ৪-vertex-এর cycle-এ ৪টি। K4-ও (সব degree 3). আর দুটি আলাদা ত্রিভুজ: সব degree ঠিক 2, তবু একটি cycle নয়, দুটি (scratch-এ degree গুনে মেলানো)।
- সঠিক দাবি: δ ≥ 2 হলে graph-এ একটি cycle আছে; আর একটি connected 2-regular simple graph একটি cycle. দ্বিতীয়টিতে দুটি শর্তই লাগে, যা ত্রিভুজ-জোড়া আর diamond দেখায়।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রম“যে graph-এ কোনো odd cycle নেই, তা দুই রঙে রং করা যায়” প্রমাণের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- প্রতিটি connected অংশ আলাদাভাবে ধরে একটি মূল vertex r বাছাই
- r থেকে দূরত্বের parity অনুযায়ী প্রতিটি vertex-কে রং দেওয়া
- ধরে নেওয়া যে কোনো edge uv-এর দুই প্রান্তে একই রং, ফলে d(u) = d(v)
- r থেকে u আর v-এর সবচেয়ে ছোট path-এর শেষ সাধারণ vertex w নিয়ে বিজোড় দৈর্ঘ্যের cycle গড়া
- অনুমানের সঙ্গে বিরোধ, তাই রংটি একটি সঠিক 2-colouring
একটি simple graph-এর vertex-গুলোর degree 4, 3, 3, 2 আর 2. graph-টিতে কয়টি edge?
- 14
- 7
- 5
- এমন graph অসম্ভব
নিচের কোন তালিকাটি কোনো simple graph-এর degree sequence হতে পারে না?
- (3, 3, 3, 3)
- (2, 2, 2, 2)
- (3, 2, 2, 1)
- (3, 3, 3, 1)
নিচের কোন graph-টি bipartite?
- Q₄ (৪-মাত্রার hypercube)
- C₇
- K₃
- W₄
5-মাত্রার hypercube Q₅-এ কয়টি edge আছে?
- 32
- 80
- 160
- 40
vertex সেট {1, 2, 3, 4} নির্দিষ্ট (নামযুক্ত)। এর ওপর কয়টি আলাদা simple undirected graph আছে?
- 11
- 16
- 64
- 4096
৭টি vertex-এর একটি simple graph-এ সব vertex-এর degree k. নিচের কোন k অসম্ভব?
- 2
- 4
- 3
- 6
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- সংজ্ঞা আগে: simple graph-এ loop বা parallel edge নেই; multigraph-এ parallel edge, pseudograph-এ loop-ও; directed graph-এ edge-এর দিক আছে। প্রতিটি উপপাদ্যের সঙ্গে ধরনটি মিলিয়ে নিন।
- Handshake: ∑ deg(v) = 2|E| (loop দুবার গোনা), তাই বিজোড় vertex জোড় সংখ্যক; directed graph-এ ∑ in = ∑ out = |E|.
- পরিবার: Kn-এ C(n, 2), Cn-এ n, Wn-এ 2n, Qn-এ n · 2n−1, Km,n-এ mn edge; k-regular n-vertex graph আছে ⇔ k ≤ n − 1 আর nk জোড়।
- Bipartite: দুই দল ⇔ দুই রং ⇔ odd cycle নেই; BFS দুই দিকের উত্তরই সাক্ষ্যসহ দেয়।
- Degree sequence আর গোনা: জোড় যোগফল জরুরি কিন্তু যথেষ্ট নয়, Havel–Hakimi বা Erdős–Gallai লাগে; নামযুক্ত n-vertex-এ simple graph 2C(n,2)টি।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৫৮ · গ্রাফের representation আর isomorphismপরবর্তী পর্বAdjacency matrix, incidence matrix আর দুটি graph একই আকৃতির কি না যাচাই।
- পর্ব ৩৭ · গণনার কৌশল — lattice path, bijection আর double countingপুনরালোচনাHandshake প্রমাণের পেছনের double counting কৌশল।
- পর্ব ৫২ · Relation আর তার ধর্ম — reflexive, symmetric, transitiveপুনরালোচনাDirected graph আর relation একই জিনিসের দুই রূপ।
- ডিসক্রিট ম্যাথমেটিক্স · কোর্স হোম৮৩টি পর্বপুরো কোর্সের মানচিত্র আর ১৪টি মডিউল।
- DSA · পর্ব ৩৯ · গ্রাফ — উপস্থাপন আর পরিভাষাকোডে প্রয়োগGraph কোডে রাখার উপায় আর তাদের খরচ।
- DSA · পর্ব ৪০ · Breadth-first search (BFS)কোডে প্রয়োগস্তরে স্তরে খোঁজা, bipartite পরীক্ষার কোড।