graph LR A((A)) -- 10 --- B((B)) A -- 15 --- C((C)) A -- 12 --- D((D)) B -- 8 --- C((C)) B -- 9 --- D((D)) C -- 11 --- D((D)) style A fill:#e0f2f1,stroke:#00695c,stroke-width:3px style B fill:#e0f2f1,stroke:#00695c,stroke-width:3px style C fill:#e0f2f1,stroke:#00695c,stroke-width:3px style D fill:#e0f2f1,stroke:#00695c,stroke-width:3px
graph LR i((i)) -- w_ij --- j((j)) i -- w_ik --- k((k)) j -- w_jk --- k style i fill:#ffe0b2,stroke:#e65100,stroke-width:3px style j fill:#e0f7fa,stroke:#00838f,stroke-width:3px style k fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px
flowchart TD A["Complete Graph G"] --> B["๐ฒ MST"] B --> C["๐ข Odd-degree nodes O"] C --> D["๐ Min Perfect Matching M on O"] B --> E["๐ Combine MST โช M โ Multigraph"] D --> E E --> O((o)) style A fill:#fff9c4,stroke:#f57f17,stroke-width:3px
flowchart TD O((o)) --> F["๐ Eulerian Circuit"] F --> G["โ๏ธ Shortcut โ Hamiltonian Cycle"] G --> H["โ TSP Tour (โค 1.5ร OPT)"] style H fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px
graph TB subgraph "MST (n=6)" 0((0)) --- 1((1)) 0 --- 2((2)) 1 --- 3((3)) 1 --- 4((4)) 4 --- 5((5)) end style 0 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 1 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 2 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 3 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 4 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 5 fill:#fff9c4,stroke:#f57f17,stroke-width:3px
graph TB 0((0)) ---|deg=2| 1((1)) 0 ---|deg=2| 2((2)) 1 ---|deg=3| 3((3)) 1 ---|deg=3| 4((4)) 4 ---|deg=3| 5((5)) style 1 fill:#ffcdd2,stroke:#c62828,stroke-width:3px style 2 fill:#ffcdd2,stroke:#c62828,stroke-width:3px style 3 fill:#ffcdd2,stroke:#c62828,stroke-width:3px style 5 fill:#ffcdd2,stroke:#c62828,stroke-width:3px
graph TB subgraph "MST edges (solid)" 0((0)) --- 1((1)) 0 --- 2((2)) 1 --- 3((3)) 1 --- 4((4)) 4 --- 5((5)) end subgraph "Matching edges (dashed)" 2 -.- 3 4 -.- 5 end style 0 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 1 fill:#ffcdd2,stroke:#c62828,stroke-width:3px style 2 fill:#ffcdd2,stroke:#c62828,stroke-width:3px style 3 fill:#ffcdd2,stroke:#c62828,stroke-width:3px style 4 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 5 fill:#ffcdd2,stroke:#c62828,stroke-width:3px
graph TB subgraph "Combined Multigraph" 0((0)) --- 1((1)) 0 --- 2((2)) 1 === 3((3)) 1 --- 4((4)) 2 === 3((3)) 4 === 5((5)) 4 --- 5((5)) end style 0 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 1 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 2 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 3 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 4 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 5 fill:#fff9c4,stroke:#f57f17,stroke-width:3px
graph LR subgraph "Eulerian Walk" direction LR 0 --> 1 --> 3 --> 2 --> 0 --> 2 end style 0 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 1 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 2 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 3 fill:#fff9c4,stroke:#f57f17,stroke-width:3px
graph TB 0((โ )) === 1((โก)) 0 === 2((โข)) 0 -.-x|visited twice| 2 1 === 3((โฃ)) 1 === 4((โค)) 2 === 3 4 === 5((โฅ)) 4 -.-x 5 linkStyle 0 stroke:#4c4,stroke-width:2px linkStyle 1 stroke:#4c4,stroke-width:2px linkStyle 2 stroke:#4c4,stroke-width:2px linkStyle 3 stroke:#4c4,stroke-width:2px linkStyle 4 stroke:#4c4,stroke-width:2px linkStyle 5 stroke:#4c4,stroke-width:2px style 0 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 1 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 2 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 3 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 4 fill:#fff9c4,stroke:#f57f17,stroke-width:3px style 5 fill:#fff9c4,stroke:#f57f17,stroke-width:3px
flowchart LR subgraph "Eulerian: 0โโ โโขโโกโโ โโฃโโคโโฃโโ โ0" A end subgraph "Shortcut: 0โโ โโขโโกโโฃโโคโ0" B end A -- "โ๏ธ remove duplicates" --> B style A fill:#e3f2fd,stroke:#1565c0,stroke-width:3px style B fill:#ffccbc,stroke:#bf360c,stroke-width:3px
xychart-beta title "Cost buildup vs OPT" x-axis ["MST", "Matching", "Total Tour", "OPT"] y-axis "Cost" 0 --> 100 bar [40, 20, 60, 45]
xychart-beta title "Best-known approximation ratios for Metric TSP" x-axis ["1976\n Christofides", "2020\n Karlin-Klein-OveisGharan", "2022\n Improved", "Ultimate Limit\n (unless P=NP)"] y-axis "Ratio" 1.0 --> 2.0 line [1.5, 1.5, 1.5, 1.0]
timeline title A Brief History of TSP 1800s : "Traveling Salesman" mentioned in German traveling salesmen manuals 1930 : Karl Menger formalizes the problem 1972 : Karp proves TSP is NP-complete ๐จ 1976 : Christofides publishes 1.5-approximation ๐ 1990s : Concorde solver cracks 1000+ city instances 2004 : 85,900-city instance solved optimally 2020s : First improvement over Christofides (by 0.0002%)
graph LR subgraph "OPT Tour" direction LR a1((โข)) --- a2((โข)) --- a3((โข)) --- a4((โข)) --- a1 end subgraph "Matching 1 (dashed)" b1((โข)) -.- b2((โข)) b3((โข)) -.- b4((โข)) end subgraph "Matching 2 (dotted)" c1((โข)) -.- c2((โข)) c3((โข)) -.- c4((โข)) end style a1 fill:#fce4ec,stroke:#880e4f,stroke-width:3px style a2 fill:#fce4ec,stroke:#880e4f,stroke-width:3px style b1 fill:#fce4ec,stroke:#880e4f,stroke-width:3px style b2 fill:#fce4ec,stroke:#880e4f,stroke-width:3px style b3 fill:#fce4ec,stroke:#880e4f,stroke-width:3px style b4 fill:#fce4ec,stroke:#880e4f,stroke-width:3px