[{"content":"In bipartite graph theory and combinatorial optimization, one of the most fundamental questions is: When can every vertex on the left side of a bipartite graph be matched to a distinct vertex on the right side?\nWhile maximum flow and augmenting path algorithms (such as Hopcroft–Karp or Kuhn\u0026rsquo;s algorithm) allow us to compute a maximum matching for a fixed graph, Hall\u0026rsquo;s Marriage Theorem (proved by Philip Hall in 1935) gives a clean necessary and sufficient structural condition for a complete matching to exist. In competitive programming, Hall\u0026rsquo;s theorem often allows us to bypass building an explicit flow network altogether—transforming matching feasibility problems into algebraic inequalities, prefix/interval checks, or Sum Over Subsets Dynamic Programming (SOS DP).\nIn this post, we will build geometric and combinatorial intuition for Hall\u0026rsquo;s Marriage Theorem, walk through two classic proofs, explore its most useful generalizations, and solve a classic hard problem: AtCoder ARC106E - Medals.\n1. Formal Statement and Intuition Definitions Let $G = (L \\cup R, E)$ be a bipartite graph with left vertex set $L$, right vertex set $R$, and edges $E \\subseteq L \\times R$.\nA matching $M \\subseteq E$ is a set of edges such that no two edges in $M$ share a common vertex. An $L$-saturating matching (or complete matching from $L$ to $R$) is a matching $M$ of size $|M| = |L|$ that covers every vertex in $L$. For any subset of left vertices $S \\subseteq L$, the neighborhood of $S$, denoted $N_G(S)$ (or simply $N(S)$), is the set of all vertices in $R$ adjacent to at least one vertex in $S$: \\[ N(S) = \\bigcup_{u \\in S} N(u) = \\{ v \\in R \\mid \\exists u \\in S \\text{ such that } (u, v) \\in E \\}. \\]Hall\u0026rsquo;s Marriage Theorem Theorem (Hall, 1935): A bipartite graph $G = (L \\cup R, E)$ has an $L$-saturating matching if and only if for every subset $S \\subseteq L$,\n\\[ |N(S)| \\ge |S|. \\]This inequality is known as Hall\u0026rsquo;s Marriage Condition.\nWhy Local Degree Checks Are Not Enough A common beginner pitfall is assuming that if $|R| \\ge |L|$ and every vertex $u \\in L$ has at least one neighbor ($|N(u)| \\ge 1$), a complete matching should exist. Consider the two bipartite graphs below:\nFigure 1: Left: Hall\u0026rsquo;s condition holds for every subset $S \\subseteq L$, yielding an $L$-saturating matching of size $4$. Right: Every vertex in $L$ has degree $\\ge 1$, yet $S = \\{u_1, u_2, u_3\\}$ only connects to $N(S) = \\{v_1, v_2\\}$, creating a bottleneck ($|N(S)| = 2 \u003c |S| = 3$).\nIn the right panel of Figure 1, the three vertices in $S = \\{u_1, u_2, u_3\\}$ collectively share only two candidate partners $N(S) = \\{v_1, v_2\\}$. By the Pigeonhole Principle, at most two vertices in $S$ can be matched, no matter how many edges $u_4$ has. Hall\u0026rsquo;s Marriage Theorem states that the absence of such bottleneck subsets is not just necessary—it is also sufficient to guarantee an $L$-saturating matching.\n2. Detailed Proofs of Hall\u0026rsquo;s Theorem To establish the theorem completely, we must prove both directions: Necessity ($\\implies$) and Sufficiency ($\\impliedby$). Below, we present the straightforward necessity proof followed by two distinct proofs of sufficiency:\nHalmos and Vaughan\u0026rsquo;s Combinatorial Induction (1950) — a purely structural proof using tight/critical subsets. Alternating Trees and Augmenting Paths — a constructive, algorithmic proof that directly connects to bipartite matching algorithms. Direction 1: Necessity ($\\implies$) Suppose $G$ has an $L$-saturating matching $M$. For any vertex $u \\in L$, let $M(u) \\in R$ denote the unique partner matched to $u$ under $M$.\nTake any subset $S \\subseteq L$. For each $u \\in S$, the edge $(u, M(u))$ belongs to $M \\subseteq E$, so $M(u) \\in N(S)$. Therefore, the set of matched partners $M(S) = \\{M(u) \\mid u \\in S\\}$ is a subset of $N(S)$. Since $M$ is a matching, all vertices in $S$ are matched to distinct vertices in $R$, meaning $|M(S)| = |S|$. Thus:\n\\[ |N(S)| \\ge |M(S)| = |S|. \\quad \\blacksquare \\] Direction 2, Proof 1: Halmos \u0026amp; Vaughan\u0026rsquo;s Inductive Proof (1950) We prove sufficiency by strong induction on $|L|$.\nBase Case ($|L| = 1$) If $L = \\{u\\}$, Hall\u0026rsquo;s condition for $S = \\{u\\}$ gives $|N(\\{u\\})| \\ge 1$. Thus $u$ has at least one neighbor $v \\in R$, and the single edge $\\{(u, v)\\}$ forms an $L$-saturating matching.\nInductive Step ($|L| \\ge 2$) Assume Hall\u0026rsquo;s theorem holds for all bipartite graphs with fewer than $|L|$ left vertices. Given $G = (L \\cup R, E)$ satisfying $|N_G(S)| \\ge |S|$ for all $S \\subseteq L$, we distinguish two cases based on whether any proper non-empty subset of $L$ satisfies Hall\u0026rsquo;s condition with equality (a tight or critical subset).\nCase 1: Every Proper Non-Empty Subset Has Strict Slack Suppose that for every proper non-empty subset $\\emptyset \\subsetneq S \\subsetneq L$, we have strict inequality:\n\\[ |N_G(S)| \\ge |S| + 1. \\]Pick any vertex $u \\in L$. Since $|N_G(\\{u\\})| \\ge 1$, we can pick a neighbor $v \\in N_G(u)$ and match $u$ with $v$. Now consider the residual graph $G' = G - \\{u, v\\}$ with left side $L' = L \\setminus \\{u\\}$ and right side $R' = R \\setminus \\{v\\}$.\nFor any non-empty subset $S \\subseteq L'$, $S$ is a proper non-empty subset of $L$. Removing $v$ from $R$ reduces the neighborhood size of $S$ by at most $1$:\n\\[ |N_{G'}(S)| = |N_G(S) \\setminus \\{v\\}| \\ge |N_G(S)| - 1 \\ge (|S| + 1) - 1 = |S|. \\]Thus, $G'$ satisfies Hall\u0026rsquo;s condition! By the induction hypothesis, $G'$ has an $L'$-saturating matching $M'$. Adding the edge $(u, v)$ to $M'$ yields an $L$-saturating matching for $G$.\nCase 2: There Exists a Tight (Critical) Proper Subset Suppose there exists some proper non-empty subset $\\emptyset \\subsetneq S \\subsetneq L$ that holds with equality:\n\\[ |N_G(S)| = |S|. \\]We decompose $G$ into two vertex-disjoint subgraphs along $S$ and $N_G(S)$:\nThe Critical Subgraph: $G_1 = G[S \\cup N_G(S)]$ with left side $S$ and right side $N_G(S)$. The Residual Subgraph: $G_2 = G[(L \\setminus S) \\cup (R \\setminus N_G(S))]$ with left side $L \\setminus S$ and right side $R \\setminus N_G(S)$. Figure 2: When a proper non-empty subset $S \\subsetneq L$ is tight ($|N_G(S)| = |S|$), we match $S$ to $N_G(S)$ in $G_1$ and match $L \\setminus S$ to $R \\setminus N_G(S)$ in $G_2$.\nLet\u0026rsquo;s verify that both $G_1$ and $G_2$ satisfy Hall\u0026rsquo;s condition:\nIn $G_1$: For any subset $A \\subseteq S$, all neighbors of $A$ in $G$ already lie inside $N_G(S)$, so $N_{G_1}(A) = N_G(A)$. Hence $|N_{G_1}(A)| = |N_G(A)| \\ge |A|$. Since $|S| \u003c |L|$, the induction hypothesis gives an $S$-saturating matching $M_1$ in $G_1$. In $G_2$: Take any subset $T \\subseteq L \\setminus S$. Consider the union $S \\cup T \\subseteq L$ in the original graph $G$. Any neighbor of $S \\cup T$ in $G$ either belongs to $N_G(S)$ or belongs to $N_G(T) \\setminus N_G(S) = N_{G_2}(T)$. Because these two sets are disjoint: \\[ N_G(S \\cup T) = N_G(S) \\sqcup N_{G_2}(T) \\implies |N_G(S \\cup T)| = |N_G(S)| + |N_{G_2}(T)|. \\]By Hall\u0026rsquo;s condition on $S \\cup T$ in $G$ (and the fact that $S \\cap T = \\emptyset$), we have:\n\\[ |N_G(S)| + |N_{G_2}(T)| = |N_G(S \\cup T)| \\ge |S \\cup T| = |S| + |T|. \\]Subtracting $|N_G(S)| = |S|$ from both sides yields:\n\\[ |N_{G_2}(T)| \\ge |T|. \\]Thus $G_2$ also satisfies Hall\u0026rsquo;s condition! Since $|L \\setminus S| \u003c |L|$, the induction hypothesis gives an $(L \\setminus S)$-saturating matching $M_2$ in $G_2$.\nFinally, because $G_1$ and $G_2$ are completely vertex-disjoint, $M = M_1 \\cup M_2$ is an $L$-saturating matching of $G$. $\\blacksquare$\nDirection 2, Proof 2: Augmenting Paths and Alternating Trees We can also prove sufficiency constructively by showing that if a matching $M$ is not $L$-saturating, Hall\u0026rsquo;s condition forces the existence of an augmenting path.\nLet $M$ be a maximum matching in $G$, and suppose for contradiction that $|M| \u003c |L|$. Then there exists at least one unmatched vertex $u_0 \\in L$.\nDefine an alternating path starting at $u_0$ as a simple path whose edges alternate between non-matching edges ($E \\setminus M$) and matching edges ($M$):\n\\[ u_0 \\xrightarrow{\\notin M} v_1 \\xrightarrow{\\in M} u_1 \\xrightarrow{\\notin M} v_2 \\xrightarrow{\\in M} u_2 \\xrightarrow{\\notin M} \\cdots \\]Let $Z$ be the set of all vertices in $G$ reachable from $u_0$ via an alternating path (including $u_0$ itself), and partition $Z$ into its left and right vertices:\n\\[ Z_L = Z \\cap L, \\qquad Z_R = Z \\cap R. \\]We make three key observations about $Z_L$ and $Z_R$:\nEvery vertex in $Z_R$ is matched by $M$: If some $v \\in Z_R$ were unmatched, the alternating path from $u_0$ to $v$ would start and end at unmatched vertices—which is an augmenting path! Flipping the status of edges along this path (replacing $M$-edges with non-$M$ edges) would create a valid matching of size $|M| + 1$, contradicting the maximality of $M$. $|Z_R| = |Z_L| - 1$: Whenever an alternating path reaches $v \\in Z_R$ from $Z_L$ via a non-matching edge, we can immediately follow $v$\u0026rsquo;s unique matching edge $(u', v) \\in M$ into $u' \\in Z_L \\setminus \\{u_0\\}$. Conversely, every vertex in $Z_L \\setminus \\{u_0\\}$ is entered along its unique matching edge from $Z_R$. Therefore, $M$ induces a one-to-one bijection between $Z_R$ and $Z_L \\setminus \\{u_0\\}$, giving: \\[ |Z_R| = |Z_L \\setminus \\{u_0\\}| = |Z_L| - 1. \\] $N_G(Z_L) = Z_R$: By definition, every $v \\in Z_R$ was reached from some vertex in $Z_L$, so $Z_R \\subseteq N_G(Z_L)$. Conversely, take any $u \\in Z_L$ and any neighbor $v \\in N_G(u)$. Since $u$ is reachable from $u_0$ via an alternating path ending with a matching edge (or is $u_0$ itself), taking the edge $(u, v)$ (if not already on the path) shows that $v$ is also reachable via an alternating path, so $v \\in Z_R$. Thus $N_G(Z_L) = Z_R$. Combining Observations 2 and 3 for the subset $S = Z_L \\subseteq L$, we obtain:\n\\[ |N_G(Z_L)| = |Z_R| = |Z_L| - 1 \u003c |Z_L|, \\]which directly contradicts Hall\u0026rsquo;s condition $|N_G(S)| \\ge |S|$! Hence no unmatched vertex $u_0 \\in L$ can exist, and $|M| = |L|$. $\\blacksquare$\nConnection to Max-Flow Min-Cut and König\u0026rsquo;s Theorem: Hall\u0026rsquo;s Marriage Theorem can also be viewed as a special case of the Max-Flow Min-Cut Theorem (by directing edges from source $s \\to L$ with capacity $1$, $L \\to R$ with capacity $\\infty$, and $R \\to t$ with capacity $1$) or König\u0026rsquo;s Theorem (maximum bipartite matching equals minimum vertex cover).\n3. Essential Generalizations for Competitive Programming In contest problems, Hall\u0026rsquo;s theorem rarely appears in its bare textbook form. Instead, you will almost always use one of the following three extensions.\n1. Hall\u0026rsquo;s Defect Formula (Maximum Matching Size) What if Hall\u0026rsquo;s condition fails for some subsets? Define the deficiency (or defect) of a subset $S \\subseteq L$ as $\\max(0, |S| - |N(S)|)$. Since at least $|S| - |N(S)|$ vertices in $S$ must remain unmatched, the maximum matching size $\\nu(G)$ is bounded by $|L| - (|S| - |N(S)|)$. In fact, equality holds for the worst bottleneck subset:\nTheorem (Ore\u0026rsquo;s / Hall\u0026rsquo;s Defect Formula): The size of a maximum matching in $G = (L \\cup R, E)$ is:\n\\[ \\nu(G) = |L| - \\max_{S \\subseteq L} \\bigl(|S| - |N(S)|\\bigr) = \\min_{S \\subseteq L} \\bigl(|L \\setminus S| + |N(S)|\\bigr). \\] (Note: Setting $S = \\emptyset$ gives $|S| - |N(S)| = 0$, so the maximum defect is always $\\ge 0$.)\n2. Generalized Hall\u0026rsquo;s Theorem ($K$-Matching / Vertex Capacities) Suppose each left vertex $u \\in L$ needs to be matched to $d(u)$ distinct vertices in $R$ (for example, each employee needs $K$ medals), while each right vertex $v \\in R$ can be used at most $1$ time (or more generally, $c(v)$ times).\nWe can reduce this directly to standard Hall\u0026rsquo;s theorem by vertex cloning: replace each $u \\in L$ with $d(u)$ identical copies $u^{(1)}, u^{(2)}, \\dots, u^{(d(u))}$, each connected to the exact same neighborhood $N(u) \\subseteq R$.\nObserve that for any subset of cloned vertices, if it contains at least one copy of $u$, adding all remaining copies of $u$ increases the subset size without increasing its neighborhood $N(S)$! Thus, the worst-case subsets always include either all $d(u)$ copies of $u$ or none of them:\nTheorem (Generalized Hall\u0026rsquo;s Condition): There exists an assignment where each $u \\in L$ receives $d(u)$ matches and each $v \\in R$ is used at most $c(v)$ times if and only if for every subset $S \\subseteq L$:\n\\[ \\sum_{v \\in N(S)} c(v) \\ge \\sum_{u \\in S} d(u). \\]In particular, when every $u \\in L$ demands $K$ matches and every $v \\in R$ has capacity $1$:\n\\[ |N(S)| \\ge K \\cdot |S| \\quad \\forall S \\subseteq L. \\] 3. The Complement Trick: From Union Size to SOS DP When $|L| = N \\le 20$ and $|R|$ is very large (e.g., $|R| \\sim 10^6$), checking $|N(S)| \\ge K \\cdot |S|$ for all $2^N$ subsets $S \\subseteq L$ requires knowing $|N(S)|$ for every subset $S$.\nComputing $N(S) = \\bigcup_{u \\in S} N(u)$ directly is difficult because set union is not additive. However, switching to the complement in $R$ turns the union into a clean subset containment condition!\nFor each right vertex $v \\in R$, let $\\text{mask}[v] = N(v) \\subseteq L$ be the bitmask of left vertices adjacent to $v$. Then:\n$v \\in N(S) \\iff \\text{mask}[v] \\cap S \\ne \\emptyset$. $v \\notin N(S) \\iff \\text{mask}[v] \\cap S = \\emptyset \\iff \\text{mask}[v] \\subseteq L \\setminus S$. Therefore, if $\\text{cnt}[M]$ is the number of right vertices $v \\in R$ with $\\text{mask}[v] = M$, and we define the Sum Over Subsets (SOS) function:\n\\[ f(T) = \\sum_{T' \\subseteq T} \\text{cnt}[T'], \\]then the number of right vertices not connected to $S$ is simply $f(L \\setminus S)$, and the neighborhood size of $S$ is:\n\\[ |N(S)| = |R| - f(L \\setminus S). \\]Using SOS DP (Fast Zeta Transform), we can compute $f(T)$ for all $2^N$ masks $T$ in $O(N \\cdot 2^N)$ time!\n4. Sample Problem: AtCoder ARC106E - Medals Problem Statement There are $N$ employees in a company, numbered $1$ to $N$. Employee $i$ follows a strict periodic work schedule determined by an integer $A_i$:\nCome to work for $A_i$ consecutive days ($d = 1, \\dots, A_i$), Take $A_i$ consecutive days off ($d = A_i + 1, \\dots, 2A_i$), Come to work for $A_i$ consecutive days ($d = 2A_i + 1, \\dots, 3A_i$), and so on. Each day, the company produces at most one medal and awards it to at most one employee who is present at work on that day.\nFind the minimum number of days $D$ needed so that every employee can be awarded at least $K$ medals.\nConstraints $1 \\le N \\le 18$ $1 \\le K \\le 10^5$ $1 \\le A_i \\le 10^5$ Step 1: Monotonicity and a Tight Upper Bound on $D$ First, notice that if $D$ days are sufficient to award $K$ medals to each of the $N$ employees, then $D + 1$ days are also sufficient. This monotonicity means we can binary search for the minimum valid day $D$.\nWhat are the lower and upper bounds for our binary search?\nLower Bound ($L_{\\text{bs}} = N K$): Since we need to award $N K$ medals in total and can award at most $1$ medal per day, we need at least $D \\ge N K$ days.\nUpper Bound ($R_{\\text{bs}} = 2 N K$): Why is $D = 2 N K$ always enough, regardless of $A_i$? Let\u0026rsquo;s analyze how many days employee $i$ works during any prefix of $D$ days. Write $D = q \\cdot (2A_i) + r$ with $0 \\le r \u003c 2A_i$:\nIn the $q$ complete cycles of $2A_i$ days, employee $i$ works $q A_i$ days (exactly half of $2 q A_i$). In the remaining $r$ days, because the work phase comes first in each cycle, employee $i$ works $\\min(r, A_i)$ days. Since $r \u003c 2A_i$, we always have $\\min(r, A_i) \\ge \\lceil r / 2 \\rceil$. Summing the two parts shows that in the first $D$ days, every employee $i$ is present at work for at least $\\lceil D / 2 \\rceil$ days!\nIn particular, when $D = 2 N K$, every single employee is at work for at least $N K$ days. Even if we greedily hand out medals, any subset $S$ of employees has $|N(S)| \\ge N K \\ge K \\cdot |S|$. Thus:\n\\[ N K \\le D_{\\min} \\le 2 N K \\le 2 \\times 18 \\times 10^5 = 3.6 \\times 10^6. \\] Step 2: Modeling with Generalized Hall\u0026rsquo;s Theorem Fix a candidate number of days $D \\in [N K, 2 N K]$. Construct a bipartite graph $G = (L \\cup R, E)$:\nLeft vertices $L = \\{0, 1, \\dots, N - 1\\}$: The $N$ employees. Each employee requires $K$ medals. Right vertices $R = \\{1, 2, \\dots, D\\}$: The first $D$ days. Each day can supply at most $1$ medal. Edges $E$: There is an edge $(i, d)$ if and only if employee $i$ comes to work on day $d$, which occurs when: \\[ (d - 1) \\bmod (2 A_i) \u003c A_i. \\]By the Generalized Hall\u0026rsquo;s Marriage Theorem, $D$ days are sufficient if and only if for every subset of employees $S \\subseteq L$:\n\\[ |N(S)| \\ge K \\cdot |S|, \\]where $N(S) \\subseteq \\{1, \\dots, D\\}$ is the set of days on which at least one employee in $S$ is at work.\nStep 3: Complement Counting \u0026amp; SOS DP Since $N \\le 18$, there are $2^{18} = 262{,}144$ subsets $S \\subseteq L$. Using the Complement Trick from Section 3.3, we represent the set of employees working on day $d$ as an $N$-bit integer $\\text{mask}[d] \\in [0, 2^N - 1]$:\n\\[ \\text{mask}[d] = \\sum_{i \\text{ works on day } d} 2^i. \\]\nFigure 3: For a subset $S \\subseteq L$, the days in $R \\setminus N(S)$ are precisely the days $d \\le D$ where no employee in $S$ works ($\\text{mask}[d] \\subseteq L \\setminus S$). Counting these via SOS DP gives $|N(S)| = D - f(L \\setminus S)$.\nLet $U = (2^N - 1)$ be the full bitmask of all $N$ employees. For any subset $S \\subseteq L$, a day $d \\in \\{1, \\dots, D\\}$ does not belong to $N(S)$ if and only if $\\text{mask}[d] \\cap S = \\emptyset$, or equivalently:\n\\[ \\text{mask}[d] \\subseteq U \\oplus S. \\]Thus, to check whether a fixed $D$ is valid:\nBuild a frequency array $\\text{cnt}[0 \\dots 2^N - 1]$ where $\\text{cnt}[m]$ counts how many days $d \\in \\{1, \\dots, D\\}$ have $\\text{mask}[d] = m$. Run SOS DP in $O(N 2^N)$ time to compute: \\[ f[T] = \\sum_{T' \\subseteq T} \\text{cnt}[T'] \\quad \\text{for all } T \\in [0, 2^N - 1]. \\] Verify that for every mask $S \\in [1, 2^N - 1]$: \\[ D - f[U \\oplus S] \\ge K \\cdot \\operatorname{popcount}(S). \\] Performance Optimization: Instead of recomputing employee attendance from scratch inside each binary search iteration, we can precompute the array mask[1 .. 2NK] once before the binary search in $O(N \\cdot NK) = O(N^2 K)$ time! Inside check(D), building cnt is then just a fast $O(D)$ loop.\nStep 4: Walkthrough on Sample 1 Consider Sample 1: $N = 3$, $K = 3$, and $A = [1, 2, 3]$. Here $N K = 9$ and $2 N K = 18$. Let\u0026rsquo;s inspect the daily attendance bitmasks for the first $D = 10$ days:\nDay $d$ Emp 0 ($A_0=1$) Emp 1 ($A_1=2$) Emp 2 ($A_2=3$) $\\text{mask}[d]$ (binary) $1$ $\\checkmark$ $\\checkmark$ $\\checkmark$ 111 ($7$) $2$ $\\cdot$ $\\checkmark$ $\\checkmark$ 110 ($6$) $3$ $\\checkmark$ $\\cdot$ $\\checkmark$ 101 ($5$) $4$ $\\cdot$ $\\cdot$ $\\cdot$ 000 ($0$) $5$ $\\checkmark$ $\\checkmark$ $\\cdot$ 011 ($3$) $6$ $\\cdot$ $\\checkmark$ $\\cdot$ 010 ($2$) $7$ $\\checkmark$ $\\cdot$ $\\checkmark$ 101 ($5$) $8$ $\\cdot$ $\\cdot$ $\\checkmark$ 100 ($4$) $9$ $\\checkmark$ $\\checkmark$ $\\checkmark$ 111 ($7$) $10$ $\\cdot$ $\\checkmark$ $\\cdot$ 010 ($2$) Why $D = 9$ fails: Look at Day $4$, where $\\text{mask}[4] = \\texttt{000}_2$ (nobody comes to work). For the full set $S = \\{0, 1, 2\\}$ ($|S| = 3$), its complement is $U \\oplus S = \\texttt{000}_2$, and $f[\\texttt{000}_2] = \\text{cnt}[\\texttt{000}_2] = 1$ (Day $4$). Thus at $D = 9$: \\[ |N(\\{0, 1, 2\\})| = 9 - f[\\texttt{000}_2] = 9 - 1 = 8 \u003c K \\cdot |S| = 9. \\] Why $D = 10$ succeeds: At $D = 10$, $|N(\\{0, 1, 2\\})| = 10 - 1 = 9 \\ge 9$, and every single-employee and two-employee subset also satisfies $10 - f[U \\oplus S] \\ge 3|S|$. Thus the minimum number of days is $10$. Complexity Analysis Time Complexity: Precomputation: Marking work intervals for each of the $N$ employees up to $2NK$ takes $O(N \\cdot 2NK) = O(N^2 K)$ operations ($\\approx 6.4 \\times 10^7$ simple bitwise ORs). Binary Search: The search range $[NK, 2NK]$ has length $NK \\le 1.8 \\times 10^6$, requiring $\\lceil \\log_2(NK) \\rceil \\le 21$ iterations. Each call to check(D) takes $O(D)$ to populate f and $O(N 2^N)$ for the SOS DP. Total Time: \\[ O\\bigl(N^2 K + (N K + N 2^N) \\log(N K)\\bigr). \\] For $N = 18$ and $K = 10^5$, $N 2^N \\approx 4.7 \\times 10^6$, which runs in $\\sim 0.25$ seconds in C++. Space Complexity: $O(N K + 2^N)$ to store day_mask (size $3.6 \\times 10^6$) and the SOS DP array f (size $2^{18} = 262{,}144$), using less than $18\\text{ MB}$ of memory. 5. Summary Cheat Sheet Variant / Technique Mathematical Formulation Typical Use Case Standard Hall\u0026rsquo;s Theorem $\\forall S \\subseteq L,\\; \\lvert N(S)\\rvert \\ge \\lvert S\\rvert$ Proving existence of an $L$-saturating matching Hall\u0026rsquo;s Defect Formula $\\nu(G) = \\lvert L\\rvert - \\max_{S \\subseteq L} (\\lvert S\\rvert - \\lvert N(S)\\rvert)$ Finding maximum matching size when bottlenecks exist Generalized $K$-Matching $\\forall S \\subseteq L,\\; \\lvert N(S)\\rvert \\ge K \\cdot \\lvert S\\rvert$ Assigning $K$ distinct resources to each left vertex Complement + SOS DP $\\lvert N(S)\\rvert = \\lvert R\\rvert - \\sum_{T \\subseteq L \\setminus S} \\text{cnt}[T]$ Fast $O(N 2^N)$ verification when $\\lvert L\\rvert \\le 20$ and $\\lvert R\\rvert$ is large ","permalink":"https://blog-b18008.gitlab.io/posts/halls-marriage-theorem/","summary":"\u003cp\u003eIn bipartite graph theory and combinatorial optimization, one of the most fundamental questions is: \u003cstrong\u003eWhen can every vertex on the left side of a bipartite graph be matched to a distinct vertex on the right side?\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eWhile maximum flow and augmenting path algorithms (such as Hopcroft–Karp or Kuhn\u0026rsquo;s algorithm) allow us to \u003cem\u003ecompute\u003c/em\u003e a maximum matching for a fixed graph, \u003cstrong\u003eHall\u0026rsquo;s Marriage Theorem\u003c/strong\u003e (proved by Philip Hall in 1935) gives a clean \u003cstrong\u003enecessary and sufficient structural condition\u003c/strong\u003e for a complete matching to exist. In competitive programming, Hall\u0026rsquo;s theorem often allows us to bypass building an explicit flow network altogether—transforming matching feasibility problems into algebraic inequalities, prefix/interval checks, or \u003cstrong\u003eSum Over Subsets Dynamic Programming (SOS DP)\u003c/strong\u003e.\u003c/p\u003e","title":"Hall's Marriage Theorem: Intuition, Proofs, and Competitive Programming Applications"},{"content":"Counting the number of valid bracket (parenthesis) sequences formed by $n$ opening brackets ( and $n$ closing brackets ) is one of the most celebrated problems in combinatorics and computer science.\nWhether you are parsing expressions, counting binary trees, or analyzing stack permutations, the answer is always the $n$-th Catalan number:\n\\[ C_n = \\frac{1}{n+1}\\binom{2n}{n} = \\binom{2n}{n} - \\binom{2n}{n+1}. \\]In this post, we will formally define valid bracket sequences, build geometric intuition using lattice paths (Dyck paths), and prove the closed-form formula using André\u0026rsquo;s Reflection Principle as well as the first-return recurrence relation.\n1. What Makes a Bracket Sequence Valid? A sequence of length $2n$ consisting of $n$ opening brackets ( and $n$ closing brackets ) is valid (or well-formed) if and only if:\nTotal Balance: There are exactly $n$ opening brackets ( and $n$ closing brackets ). Prefix Balance: In every prefix of the sequence, the number of closing brackets ) never exceeds the number of opening brackets (. For small values of $n$, we can list all valid sequences directly:\n$n$ Valid Bracket Sequences Count ($C_n$) $0$ $\\epsilon$ (empty string) $1$ $1$ () $1$ $2$ (()), ()() $2$ $3$ ((())), (()()), (())(), ()(()), ()()() $5$ $4$ $14$ distinct sequences $14$ Without condition 2, there are simply $\\binom{2n}{n}$ ways to choose which $n$ of the $2n$ positions hold (. Our goal is to determine how many of those $\\binom{2n}{n}$ sequences satisfy the prefix condition everywhere.\n2. Geometric Intuition: Lattice Paths and Dyck Paths We can translate any sequence of $n$ opening brackets ( and $n$ closing brackets ) into a monotonic path on an $n \\times n$ grid starting at $(0, 0)$ and ending at $(n, n)$:\nEach opening bracket ( moves 1 step right (East): $(x, y) \\to (x + 1, y)$. Each closing bracket ) moves 1 step up (North): $(x, y) \\to (x, y + 1)$. At any point $(x, y)$ along the path:\n$x$ is the number of ( seen so far. $y$ is the number of ) seen so far. Therefore, the Prefix Balance condition ($y \\le x$ at all times) has a clean geometric meaning:\nA bracket sequence is valid if and only if its lattice path from $(0,0)$ to $(n,n)$ never crosses above the main diagonal $y = x$.\nSuch a path is called a Dyck path of order $n$.\nFigure 1: Mapping bracket sequences of $n=3$ pairs onto a $3\\times 3$ lattice grid. Any invalid sequence must touch the forbidden line $y = x + 1$.\n3. Proof 1: André\u0026rsquo;s Reflection Principle Instead of counting valid paths directly, it is much easier to count the invalid (\u0026ldquo;bad\u0026rdquo;) paths and subtract them from the total $\\binom{2n}{n}$ paths:\n\\[ C_n = \\text{Total Paths} - \\text{Bad Paths} = \\binom{2n}{n} - \\text{Bad Paths}. \\]Characterizing Bad Paths Since steps have size $1$, a path from $(0, 0)$ to $(n, n)$ crosses above the diagonal $y = x$ if and only if it touches or crosses the forbidden line:\n\\[ y = x + 1. \\]Let $P$ be any bad path from $(0, 0)$ to $(n, n)$, and let $M = (k, k + 1)$ be the first point where $P$ touches the line $y = x + 1$.\nNow, perform a geometric reflection on the portion of $P$ that occurs after point $M$ across the line $y = x + 1$:\nEvery remaining East step (() after $M$ becomes a North step ()). Every remaining North step ()) after $M$ becomes an East step ((). Figure 2: André\u0026rsquo;s Reflection Principle. Reflecting the suffix of any bad path after its first contact $M$ with $y = x + 1$ creates a one-to-one bijection with all paths from $(0,0)$ to $(n-1, n+1)$.\nWhere Does the Reflected Path End? Let\u0026rsquo;s track the coordinates before and after $M = (k, k + 1)$:\nFrom $(0, 0)$ to $M$, the path took $k$ East steps and $k + 1$ North steps. In the original path to $(n, n)$, the remaining suffix after $M$ had to take: $n - k$ East steps, and $n - (k + 1)$ North steps. After reflecting the suffix across $y = x + 1$, the East and North steps in the suffix are swapped! So the reflected suffix takes: $n - k - 1$ East steps, and $n - k$ North steps. Adding the steps before $M$ and the reflected steps after $M$, the reflected path always terminates at:\n\\[ \\big(k + (n - k - 1),\\; (k + 1) + (n - k)\\big) = (n - 1,\\, n + 1). \\]Why Is This a Bijection? Every bad path from $(0, 0)$ to $(n, n)$ touches $y = x + 1$ at a unique first point $M$, so reflecting after $M$ maps it to a unique path from $(0, 0)$ to $(n - 1, n + 1)$. Conversely, every monotonic path from $(0, 0)$ to $(n - 1, n + 1)$ starts below $y = x + 1$ (since $0 \u003c 1$) and ends above $y = x + 1$ (since $n + 1 \u003e (n - 1) + 1$). Therefore, it must cross the line $y = x + 1$ at some first point $M$; reflecting the suffix after $M$ recovers the unique bad path to $(n, n)$. Because this mapping is a bijection, the number of bad paths from $(0, 0)$ to $(n, n)$ equals the total number of monotonic paths from $(0, 0)$ to $(n - 1, n + 1)$:\n\\[ \\text{Bad Paths} = \\binom{(n - 1) + (n + 1)}{n + 1} = \\binom{2n}{n + 1}. \\]Subtracting Bad Paths from Total Paths Subtracting the bad paths from all $\\binom{2n}{n}$ paths yields the $n$-th Catalan number:\n\\[ \\begin{aligned} C_n \u0026= \\binom{2n}{n} - \\binom{2n}{n+1} \\\\[6pt] \u0026= \\binom{2n}{n} - \\frac{n}{n+1}\\binom{2n}{n} \\\\[6pt] \u0026= \\frac{1}{n+1}\\binom{2n}{n}. \\quad \\blacksquare \\end{aligned} \\] 4. Proof 2: First-Return Decomposition \u0026amp; Recurrence We can also prove that valid bracket sequences follow the Catalan recurrence without using geometry.\nTake any non-empty valid bracket sequence $S$ of $n \\ge 1$ pairs. Its very first character must be an opening bracket (. Because $S$ is balanced, that first ( has a unique matching closing bracket ) where the prefix balance returns to $0$ for the first time.\nThis uniquely decomposes $S$ into two independent valid bracket sub-sequences $A$ and $B$:\n\\[ S = \\texttt{(} \\, A \\, \\texttt{)} \\, B \\]\nFigure 3: Every non-empty valid bracket sequence decomposes uniquely as $S = \\texttt{(} A \\texttt{)} B$, where $A$ has $k$ pairs and $B$ has $n - 1 - k$ pairs.\nInside the first matched pair, $A$ can contain $k$ pairs of brackets (where $0 \\le k \\le n - 1$) and must itself be a valid bracket sequence ($C_k$ ways). Outside, $B$ contains the remaining $n - 1 - k$ pairs of brackets and must also be a valid bracket sequence ($C_{n - 1 - k}$ ways). Summing over all possible sizes $k \\in \\{0, 1, \\dots, n - 1\\}$ gives the Catalan recurrence relation:\n\\[ C_0 = 1, \\qquad C_n = \\sum_{k=0}^{n-1} C_k \\, C_{n-1-k} \\quad (n \\ge 1). \\]Using ordinary generating functions $G(x) = \\sum_{n=0}^{\\infty} C_n x^n$, the convolution above translates to:\n\\[ G(x) = 1 + x \\, G(x)^2 \\implies G(x) = \\frac{1 - \\sqrt{1 - 4x}}{2x}, \\]whose Taylor expansion via the generalized binomial theorem yields the exact same formula $C_n = \\frac{1}{n+1}\\binom{2n}{n}$.\n5. Summary Perspective Key Idea Formula Subtraction / Reflection Total paths to $(n,n)$ minus paths touching $y = x + 1$ $\\displaystyle\\binom{2n}{n} - \\binom{2n}{n+1}$ Closed Form Algebraic simplification of the reflection formula $\\displaystyle\\frac{1}{n+1}\\binom{2n}{n}$ Recursive Decomposition Partition at first return to zero: $S = \\texttt{(} A \\texttt{)} B$ $\\displaystyle\\sum_{k=0}^{n-1} C_k C_{n-1-k}$ ","permalink":"https://blog-b18008.gitlab.io/posts/catalan-numbers-valid-bracket-sequences/","summary":"\u003cp\u003eCounting the number of \u003cstrong\u003evalid bracket (parenthesis) sequences\u003c/strong\u003e formed by $n$ opening brackets \u003ccode\u003e(\u003c/code\u003e and $n$ closing brackets \u003ccode\u003e)\u003c/code\u003e is one of the most celebrated problems in combinatorics and computer science.\u003c/p\u003e\n\u003cp\u003eWhether you are parsing expressions, counting binary trees, or analyzing stack permutations, the answer is always the $n$-th \u003cstrong\u003eCatalan number\u003c/strong\u003e:\u003c/p\u003e\n\\[\nC_n = \\frac{1}{n+1}\\binom{2n}{n} = \\binom{2n}{n} - \\binom{2n}{n+1}.\n\\]\u003cp\u003eIn this post, we will formally define valid bracket sequences, build geometric intuition using \u003cstrong\u003elattice paths (Dyck paths)\u003c/strong\u003e, and prove the closed-form formula using \u003cstrong\u003eAndré\u0026rsquo;s Reflection Principle\u003c/strong\u003e as well as the \u003cstrong\u003efirst-return recurrence relation\u003c/strong\u003e.\u003c/p\u003e","title":"Why the Number of Valid Bracket Sequences Is the Catalan Number"},{"content":"In combinatorics and algorithm design, a classic family of counting problems asks: How many ways can we choose $k$ items from $n$ distinct types when repetition is allowed? Equivalently, how many integer solutions exist for a linear equation under various boundary constraints?\nThis post breaks down the Stars and Bars (also known as the dividers or balls and urns) method across three canonical scenarios:\nUnbounded repetition ($x_i \\ge 0$) At least one of each type ($x_i \\ge 1$) Lower and upper bounds ($l_i \\le x_i \\le u_i$) via Inclusion-Exclusion and Dynamic Programming 1. Combinations with Repetition ($x_i \\ge 0$) Problem Statement Suppose we have $n$ types of items and want to select $k$ items in total, where:\nRepetition is allowed (we can pick multiple items of the same type, up to $k$), and Order does not matter (only the count of each type matters). The total number of ways to make this selection is:\n\\[ \\binom{n+k-1}{k} = \\binom{n+k-1}{n-1}. \\]Equivalence to Non-Negative Integer Solutions Let $x_i$ denote the number of items chosen from type $i$ (for $i = 1, 2, \\dots, n$). Because we choose $k$ items in total and may choose zero or more of each type, this problem is strictly equivalent to counting the number of non-negative integer solutions to the equation:\n\\[ x_1 + x_2 + \\cdots + x_n = k, \\quad x_i \\ge 0. \\]Why Does $\\binom{n+k-1}{k}$ Work? Imagine representing the $k$ chosen items as $k$ identical stars ($\\star$) and using $n - 1$ bars ($|$) as dividers to separate the stars into $n$ bins (one bin per item type):\nEverything to the left of the first bar belongs to $x_1$. Everything between the $(i-1)$-th and $i$-th bar belongs to $x_i$. Everything to the right of the $(n-1)$-th bar belongs to $x_n$. Two adjacent bars ($||$) simply mean the bin between them has $0$ items. For example, with $n = 4$ types and $k = 5$ items, the configuration:\n\\[ \\star \\star \\mid \\mid \\star \\star \\star \\mid \\]corresponds to the solution $(x_1, x_2, x_3, x_4) = (2, 0, 3, 0)$, which sums to $5$.\nIn total, there are $k$ stars and $n - 1$ bars, giving $n + k - 1$ symbols in a row. Choosing the positions of the $k$ stars (or equivalently, the $n - 1$ bars) completely determines the solution:\n\\[ \\binom{n+k-1}{k} = \\binom{n+k-1}{n-1}. \\] 2. Choosing at Least One of Each Type ($x_i \\ge 1$) Problem Statement Now suppose we must select at least one item of each of the $n$ types (assuming $k \\ge n$). This is equivalent to counting the positive integer solutions to:\n\\[ x_1 + x_2 + \\cdots + x_n = k, \\quad x_i \\ge 1. \\]The number of solutions is:\n\\[ \\binom{k-1}{n-1}. \\]Two Ways to Derive This Result Method A: The Gap / Divider Intuition Place the $k$ identical items ($\\star$) in a line:\n\\[ \\star \\;\\underbrace{\\_}_{\\text{gap } 1}\\; \\star \\;\\underbrace{\\_}_{\\text{gap } 2}\\; \\star \\;\\cdots\\; \\star \\;\\underbrace{\\_}_{\\text{gap } k-1}\\; \\star \\]There are $k - 1$ internal gaps between adjacent stars. Because no bin can be empty ($x_i \\ge 1$), no two bars can occupy the same gap, nor can a bar be placed outside the outer stars. Thus, we simply choose $n - 1$ distinct gaps out of the $k - 1$ available gaps to insert our dividers:\n\\[ \\binom{k-1}{n-1}. \\]Method B: Variable Substitution Pre-allocate $1$ item to each of the $n$ variables by defining $y_i = x_i - 1$. Since $x_i \\ge 1$, we have $y_i \\ge 0$, and the equation transforms into:\n\\[ (y_1 + 1) + (y_2 + 1) + \\cdots + (y_n + 1) = k \\implies y_1 + y_2 + \\cdots + y_n = k - n, \\quad y_i \\ge 0. \\]Applying the unbounded formula from Section 1 with $k' = k - n$ gives:\n\\[ \\binom{n + (k - n) - 1}{k - n} = \\binom{k - 1}{k - n} = \\binom{k - 1}{n - 1}. \\] 3. Bounded Variables ($0 \\le x_i \\le u_i$) In many practical problems, each variable is constrained by both a lower bound and an upper bound:\n\\[ x_1 + x_2 + \\cdots + x_n = k, \\quad l_i \\le x_i \\le u_i. \\]First, any lower bound $x_i \\ge l_i$ can be normalized to zero via the substitution $x_i' = x_i - l_i$, which reduces the target sum to $k' = k - \\sum_{i=1}^n l_i$ and the upper bounds to $u_i' = u_i - l_i$. Thus, we only need to focus on:\n\\[ x_1 + x_2 + \\cdots + x_n = k, \\quad 0 \\le x_i \\le u_i. \\]There are two standard techniques to handle upper bounds: Inclusion-Exclusion and Dynamic Programming.\nApproach 1: Principle of Inclusion-Exclusion (PIE) To count solutions satisfying $0 \\le x_i \\le u_i$, we start with all non-negative solutions ($x_i \\ge 0$) and subtract solutions that violate at least one upper bound.\nLet $P_i$ be the property that variable $x_i$ violates its upper bound, i.e.,\n\\[ x_i \\ge u_i + 1. \\]For any subset of indices $S \\subseteq \\{1, 2, \\dots, n\\}$, how many non-negative integer solutions violate all upper bounds in $S$ simultaneously (meaning $x_i \\ge u_i + 1$ for all $i \\in S$)?\nBy pre-subtracting $u_i + 1$ from each $x_i$ ($i \\in S$), the remaining sum is:\n\\[ k_S = k - \\sum_{i \\in S} (u_i + 1). \\]If $k_S \\ge 0$, the number of such solutions is $\\binom{n + k_S - 1}{n - 1}$ (and $0$ if $k_S \u003c 0$).\nBy the Principle of Inclusion-Exclusion, the exact number of valid bounded solutions is:\n\\[ \\sum_{S \\subseteq \\{1, \\dots, n\\}} (-1)^{|S|} \\binom{n + k - \\sum_{i \\in S}(u_i + 1) - 1}{n - 1}, \\]where binomial coefficients with a negative upper index (when $k_S \u003c 0$) are treated as $0$.\nSpecial Case: Uniform Upper Bound ($u_i = u$ for all $i$) When every variable shares the same upper bound $0 \\le x_i \\le u$, all subsets $S$ of size $j = |S|$ subtract the same amount $j(u + 1)$. The PIE sum simplifies to an $O(n)$ loop:\n\\[ \\sum_{j=0}^{\\lfloor k / (u+1) \\rfloor} (-1)^j \\binom{n}{j} \\binom{n + k - j(u+1) - 1}{n - 1}. \\] Approach 2: Dynamic Programming (DP) When the upper bounds $u_i$ are distinct and $n$ is too large for an $O(2^n)$ subset enumeration (e.g., $n = 100, k = 1000$), Dynamic Programming is the method of choice.\nState Definition Let $dp[i][s]$ be the number of ways to choose values for the first $i$ variables ($x_1, \\dots, x_i$) such that their sum equals $s$.\nTransition For the $i$-th variable, we can pick any value $v \\in [0, \\min(u_i, s)]$:\n\\[ dp[i][s] = \\sum_{v = 0}^{\\min(u_i, s)} dp[i-1][s - v]. \\]Notice that the right-hand side is a contiguous range sum over $dp[i-1][\\dots]$ from index $s - \\min(u_i, s)$ to $s$. Using prefix sums, each state transition takes $O(1)$ time, reducing the overall time complexity from $O(n k^2)$ to $O(n k)$ and space complexity to $O(k)$.\nPython Implementation ($O(nk)$ Time, $O(k)$ Space) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def count_bounded_solutions(u: list[int], k: int, mod: int = 10**9 + 7) -\u0026gt; int: \u0026#34;\u0026#34;\u0026#34; Counts integer solutions to x_1 + x_2 + ... + x_n = k subject to 0 \u0026lt;= x_i \u0026lt;= u[i - 1], using prefix-sum optimized DP. \u0026#34;\u0026#34;\u0026#34; dp = [0] * (k + 1) dp[0] = 1 for bound in u: # Compute prefix sums of the previous DP row prefix = [0] * (k + 2) for s in range(k + 1): prefix[s + 1] = (prefix[s] + dp[s]) % mod # Transition in O(1) per sum s: # new_dp[s] = sum(dp[s - bound : s + 1]) new_dp = [0] * (k + 1) for s in range(k + 1): left = max(0, s - bound) new_dp[s] = (prefix[s + 1] - prefix[left]) % mod dp = new_dp return dp[k] Summary Cheat Sheet Constraint on $\\sum_{i=1}^n x_i = k$ Formula / Method Time Complexity Unbounded ($x_i \\ge 0$) $\\displaystyle\\binom{n+k-1}{k} = \\binom{n+k-1}{n-1}$ $O(1)$ with precomputed factorials Positive ($x_i \\ge 1$) $\\displaystyle\\binom{k-1}{n-1}$ $O(1)$ with precomputed factorials Lower bounds ($x_i \\ge l_i$) Substitute $x_i' = x_i - l_i$, solve for $k' = k - \\sum l_i$ $O(n)$ Uniform upper bound ($0 \\le x_i \\le u$) PIE: $\\displaystyle\\sum_{j} (-1)^j \\binom{n}{j}\\binom{n + k - j(u+1) - 1}{n-1}$ $O\\left(\\min\\left(n, \\frac{k}{u+1}\\right)\\right)$ General bounds ($0 \\le x_i \\le u_i$, small $n$) Subset Inclusion-Exclusion $O(2^n)$ General bounds ($0 \\le x_i \\le u_i$, medium $k$) Prefix-sum optimized DP $O(nk)$ ","permalink":"https://blog-b18008.gitlab.io/posts/stars-and-bars-combinations-with-repetition/","summary":"\u003cp\u003eIn combinatorics and algorithm design, a classic family of counting problems asks: \u003cem\u003eHow many ways can we choose $k$ items from $n$ distinct types when repetition is allowed?\u003c/em\u003e Equivalently, how many integer solutions exist for a linear equation under various boundary constraints?\u003c/p\u003e\n\u003cp\u003eThis post breaks down the \u003cstrong\u003eStars and Bars\u003c/strong\u003e (also known as the \u003cem\u003edividers\u003c/em\u003e or \u003cem\u003eballs and urns\u003c/em\u003e) method across three canonical scenarios:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUnbounded repetition\u003c/strong\u003e ($x_i \\ge 0$)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAt least one of each type\u003c/strong\u003e ($x_i \\ge 1$)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLower and upper bounds\u003c/strong\u003e ($l_i \\le x_i \\le u_i$) via \u003cstrong\u003eInclusion-Exclusion\u003c/strong\u003e and \u003cstrong\u003eDynamic Programming\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003chr\u003e\n\u003ch2 id=\"1-combinations-with-repetition-\"\u003e1. Combinations with Repetition ($x_i \\ge 0$)\u003c/h2\u003e\n\u003ch3 id=\"problem-statement\"\u003eProblem Statement\u003c/h3\u003e\n\u003cp\u003eSuppose we have $n$ types of items and want to select $k$ items in total, where:\u003c/p\u003e","title":"Combinations with Repetition and the Stars and Bars Method"},{"content":"Welcome to iAlgorithm!\nThis blog is dedicated to exploring algorithms, data structures, systems design, and practical software engineering.\n","permalink":"https://blog-b18008.gitlab.io/about/","summary":"\u003cp\u003eWelcome to \u003cstrong\u003eiAlgorithm\u003c/strong\u003e!\u003c/p\u003e\n\u003cp\u003eThis blog is dedicated to exploring algorithms, data structures, systems design, and practical software engineering.\u003c/p\u003e","title":"About"}]