Đếm đồ thị
Trong tổ hợp, đếm đồ thị (Graph Enumeration) là nhánh nghiên cứu các bài toán đếm số đồ thị thỏa mãn một tính chất nhất định. Hàm sinh、định lý đếm Polya và phương pháp ký hiệu, cùng với OEIS, là những công cụ toán học quan trọng nhất để giải các bài toán loại này. Đếm đồ thị có thể chia thành hai loại chính: có nhãn và không nhãn. Trong đa số trường hợp1, bài toán có nhãn thường đơn giản hơn bài toán không nhãn tương ứng, vì vậy ta sẽ xét trước các bài toán có nhãn.
Cây có nhãn
Chính là công thức Cayley, xem bài dãy Prüfer. Ta cũng có thể dùng định lý cây ma trận Kirchhoff hoặc hàm sinh và định lý Lagrange để suy ra kết quả này.
Bài tập
Đồ thị liên thông có nhãn
Ví dụ “POJ 1737” Connected Graph
Ví dụ “POJ 1737” Connected Graph
Tóm tắt đề: đếm số đồ thị liên thông có nhãn với \(n\) đỉnh (\(n \leq 50\)).
Loại bài này xuất hiện sớm trong loạt “8 bài đàn ông” của Lou. Đặt \(g_n\) là số đồ thị có nhãn trên \(n\) đỉnh, \(c_n\) là dãy cần tìm. Với \(n\) đỉnh, số cạnh tối đa là \(\binom{n}{2}\), mỗi cạnh có/không có độc lập nên \(g_n = 2^{\binom{n}{2}}\). Cố định một đỉnh, liệt kê kích thước thành phần liên thông chứa nó, ta cần chọn thêm \(i-1\) đỉnh từ \(n-1\) đỉnh còn lại để tạo thành thành phần liên thông. Các đỉnh ngoài thành phần có thể nối cạnh tùy ý, nên có quan hệ đệ quy:
Chuyển vế ta được công thức đệ quy \(O(n^2)\) cho \(c_n\), đủ để AC bài này.
Ví dụ “Bài tập đội tuyển 2013” Quy hoạch thành phố
Ví dụ “Bài tập đội tuyển 2013” Quy hoạch thành phố
Tóm tắt đề: đếm số đồ thị liên thông có nhãn trên \(n\) đỉnh (\(n \leq 130000\)).
Với phạm vi lớn hơn, ta thường cần xây dựng hàm sinh để dùng các thuật toán đa thức nhanh.
Cách 1: chia để trị + FFT
Công thức đệ quy trên có dạng tự chập, nên có thể dùng FFT chia để trị, độ phức tạp \(O(n\log^2n)\).
Cách 2: nghịch đảo đa thức
Khai triển tổ hợp trong công thức đệ quy và biến đổi:
Xây dựng đa thức:
Thế vào được \(CG = H\), dùng nghịch đảo đa thức rồi chập để tìm \(C(x)\).
Cách 3: đa thức exp
Một cách khác là dùng ý nghĩa tổ hợp của exp trong EGF. Gọi EGF của đồ thị liên thông có nhãn và đồ thị đơn có nhãn lần lượt là \(C(x)\) và \(G(x)\), ta có:
Dùng đa thức ln để lấy \(C(x)\).
Đồ thị Euler, đồ thị hai phía có nhãn
Ví dụ “SPOJ KPGRAPHS” Counting Graphs
Ví dụ “SPOJ KPGRAPHS” Counting Graphs
Tóm tắt đề: đếm số đồ thị có nhãn trên \(n\) đỉnh thỏa các tính chất sau (\(n \leq 1000\)).
Bài này giới hạn độ dài code nên không thể dùng template đa thức, nhưng hàm sinh vẫn giúp phân tích.
Bài liên thông đã giải ở trên. Xét đồ thị Euler. Lưu ý các cách đếm liên thông ở trên đều có thể tổng quát cho đồ thị liên thông thỏa một tính chất bất kỳ. Ví dụ, thay \(g_n\) trong công thức liên thông hóa từ “đồ thị bất kỳ” sang “đồ thị mà bậc đỉnh đều chẵn”, khi đó \(c_n\) chính là số đồ thị Euler.
Ta gói quá trình ở POJ 1737 thành hàm liên thông hóa:
1 2 3 4 5 6 7 | |
Hai câu đầu có thể giải dễ dàng:
1 2 3 4 | |
Lưu ý quá trình liên thông hóa này tương đương với lấy log của EGF. Tương tự, ta cũng có hàm “nghịch liên thông hóa”, tương đương với exp của EGF.
1 2 3 4 5 6 7 | |
Tiếp theo bàn về đếm đồ thị hai phía có nhãn,
Gọi \(b_n\) là số đồ thị hai phía trên \(n\) đỉnh, \(g_n\) là số đồ thị trên \(n\) đỉnh được tô 2 màu sao cho các đỉnh cùng màu không có cạnh nối. Liệt kê số đỉnh của một màu, ta có2:
Sau đó ta dùng hai cách khác nhau để liên hệ \(g_n\) và \(b_n\).
Cách 1: tính hai lần
Gọi \(c_{n, k}\) là số đồ thị hai phía có \(k\) thành phần liên thông, dễ có:
So sánh hai biểu thức của \(g_n\), khai triển:
Suy ra đệ quy cho \(b_n\) với độ phức tạp \(O(n^3)\), rồi dùng bao hàm–loại trừ tối ưu còn \(O(n^2)\) để AC.
Cách 2: liên thông hóa đệ quy
Cách 2 và 3 đều dùng số đồ thị hai phía liên thông \(b1_n\) A001832 để làm cầu nối giữa \(g_n\) và \(b_n\).
Mỗi đồ thị hai phía liên thông có đúng 2 cách tô màu, ứng với hai đồ thị 2 màu liên thông khác nhau. Vì vậy, liên thông hóa \(g_n\) cho ta dãy đúng bằng \(2b1_n\), còn \(b_n\) thì lấy nghịch liên thông hóa từ \(b1_n\).
Do đó:
1 2 3 4 5 6 7 | |
Cả hai quá trình đều \(O(n^2)\), AC được bài.
Cách 3: đa thức exp
Ta cũng có thể hiểu bằng EGF.
Gọi \(G(x)\) là EGF của \(g_n\), \(B1(x)\) là EGF của \(b1_n\), \(B(x)\) là EGF của \(b_n\). Theo cách 2:
Lấy đạo hàm hai vế và so hệ số sẽ ra công thức đệ quy dễ code. Lưu ý cách 2 và 3 về bản chất là như nhau, và thường cách 3 cho thời gian tốt hơn.
Mã tham khảo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
Bài tập
- UOJ Goodbye Jihai D. 新年的追逐战
- BZOJ 3864. 大朋友和多叉树
- BZOJ 2863. 愤怒的元首
- Luogu P6295. 有标号 DAG 计数
- LOJ 6569. 仙人掌计数
- LOJ 6570. 毛毛虫计数
- Luogu P5434. 有标号荒漠计数
- Luogu P3343. [ZJOI2015] 地震后的幻想乡
- HDU 5279. YJC plays Minecraft
- Luogu P7364. 有标号二分图计数
- Luogu P5827. 点双连通图计数
- Luogu P5827. 边双连通图计数
- Luogu P6596. How Many of Them
- Luogu U152448. 有标号强连通图计数
- Project Euler 434. Rigid graphs
Công thức Riddell
Cách dùng exp trong EGF ở trên đôi khi được gọi là công thức Riddell cho đồ thị có nhãn. Hàm sinh với biến đổi Euler của phương pháp ký hiệu đôi khi cũng được gọi là công thức Riddell cho đồ thị không nhãn; dạng sau xuất hiện sớm trong nghiên cứu phân hoạch của Euler và cũng gặp trong bài toán ba lô vô hạn.
Với dãy \(a_i\) và OGF \(A(x)\) tương ứng, định nghĩa biến đổi Euler của \(A(x)\):
Gọi hệ số của \(\mathcal{E}(A(x))\) là \(b_i\), và định nghĩa mảng phụ \(c_i = \sum_{d|n} d a_d\), ta có công thức đệ quy:
Cây không nhãn
Ví dụ “SPOJ PT07D” Let us count 1 2 3
Ví dụ “SPOJ PT07D” Let us count 1 2 3
Tóm tắt đề: đếm số cây có \(n\) đỉnh thỏa các tính chất:
Cây có gốc
Trường hợp có nhãn đã giải ở trên. Xét cây có gốc không nhãn, đặt OGF là \(F(x)\), áp dụng biến đổi Euler, ta có:
Lấy hệ số là được.
Cây không gốc
Xét bao hàm–loại trừ: lấy số cây có gốc trừ đi số cây mà gốc không phải trọng tâm, và xét chẵn/lẻ của \(n\).
Khi \(n\) lẻ:
Tồn tại một cây con có kích thước \(\geq \left\lceil \frac{n}{2}\right\rceil\), liệt kê kích thước cây con:
Khi \(n\) chẵn:
Nếu có hai trọng tâm, quá trình trên chỉ trừ một lần, nên cần trừ thêm:
Ví dụ “Luogu P5900” Đếm cây không nhãn không gốc
Ví dụ “Luogu P5900” Đếm cây không nhãn không gốc
Tóm tắt đề: đếm số cây không nhãn không gốc trên \(n\) đỉnh (\(n \leq 200000\)).
Với dữ liệu lớn hơn, làm tương tự: biến đổi Euler rồi dùng template đa thức.
Đồ thị đơn không nhãn
Ví dụ “SGU 282. Isomorphism” Isomorphism
Ví dụ “SGU 282. Isomorphism” Isomorphism
Tóm tắt đề: đếm số cách tô màu \(m\) màu cho các cạnh của đồ thị đầy đủ không nhãn trên \(n\) đỉnh.
Khi \(m = 2\), đối tượng chính là đồ thị đơn không nhãn A000088. Xét định lý đếm Polya:
Nhóm hoán vị \(G\) là nhóm đối xứng bậc \(n\) của các đỉnh sinh ra hoán vị trên tập cạnh. Làm brute force cần \(O(n!)\), không thể.
Phân loại theo cấu trúc chu trình của hoán vị; mỗi cấu trúc tương ứng một phân hoạch số. Dùng dfs() sinh phân hoạch, bài toán chuyển thành tính số hoán vị \(w(p)\) ứng với phân hoạch \(p\) và số chu trình \(c(p)\) trong mỗi lớp. Đáp án:
Xét \(w(p)\): mỗi phân hoạch tương ứng một hoán vị chu trình, các phần tử cùng kích thước không phân biệt thứ tự, nên:
với \(q_i\) là số lần phần tử kích thước \(i\) xuất hiện trong \(p\).
Xét \(c(p)\): chu trình trên tập đỉnh là \(|p|\), nhưng ta quan tâm chu trình trên tập cạnh.
Nếu một cạnh nối hai đỉnh cùng một chu trình, kích thước chu trình là \(p_i\), thì số chu trình cạnh là \(\left\lfloor \frac{p_i}{2} \right\rfloor\).
Nếu một cạnh nối hai đỉnh thuộc hai chu trình khác nhau, kích thước lần lượt \(p_i,p_j\), mỗi chu trình cạnh có độ dài \(\operatorname{lcm}(p_i,p_j)\), nên số chu trình cạnh là \(\frac{p_i p_j}{\operatorname{lcm}(p_i,p_j)} = \gcd(p_i, p_j)\).
Mã tham khảo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | |
Bài tập
- CodeForces 438 E. The Child and Binary Tree
- Luogu P5448. [THUPC2018] 好图计数
- Luogu P5818. [JSOI2011] 同分异构体计数
- Luogu P6597. 烯烃计数
- Luogu P6598. 烷烃计数
- Luogu P4128. [SHOI2006] 有色图
- Luogu P4727. [HNOI2009] 图的同构计数
- AtCoder Beginner Contest 222 H. Binary Tree
- AtCoder Beginner Contest 284 Ex. Count Unlabeled Graphs
- Luogu P4708. 画画
- Luogu P7592. 数树(2021 CoE-II E)
- Luogu P5206. [WC2019] 数树
Tài liệu tham khảo và chú thích
- WC2015, Tài liệu trao đổi của học viên Gu Yuzhou: Graphical Enumeration
- WC2019, Hàm sinh, thuật toán đa thức và đếm đồ thị
- Counting labeled graphs - Algorithms for Competitive Programming
- Graphical Enumeration Paperback, Frank Harary, Edgar M. Palmer
- The encyclopedia of integer sequences, N. J. A. Sloane, Simon Plouffe
- Combinatorial Problems and Exercises, László Lovász
- Graph Theory and Additive Combinatorics
-
Có lẽ cây nhị phân không nhãn là một phản ví dụ: khi cấu trúc đủ đơn giản, nhóm hoán vị tương ứng là nhóm đồng nhất (Identity Group), khi đó phiên bản có nhãn chỉ cần nhân thêm \(n!\) là được. ↩
-
Blog của PinkRabbit cho biết dãy này cũng có thể tối ưu bằng Chirp Z-Transform. ↩
Last updated on this page:, Update history
Found an error? Want to help improve? Edit this page on GitHub!
Contributors to this page:OI-wiki
All content on this page is provided under the terms of the CC BY-SA 4.0 and SATA license, additional terms may apply