Counting labelled graphs (all, connected, acyclic directed, even), labelled trees and forests (Cayley, given degrees, rooted forests, functional graphs) and unlabelled trees (rooted and free, Otter). Spanning trees of a given graph are the Matrix-Tree Theorem; Prüfer codes and tree isomorphism are in Isomorphism and Prüfer; Comb/mint from Modular Arithmetic.
| Objects on labelled vertices | Count | Values () |
|---|---|---|
| graphs; tournaments | 1, 2, 8, 64, 1024, 32768 | |
| graphs with edges | ||
| connected graphs | ; EGF | 1, 1, 4, 38, 728, 26704 |
| graphs with all degrees even (Eulerian, not nec. connected) | 1, 1, 2, 8, 64, 1024 | |
| DAGs (Robinson) | 1, 3, 25, 543, 29281, 3781503 | |
| trees (Cayley) | 1, 1, 3, 16, 125, 1296 | |
| trees with degrees () | ||
| forests of trees rooted at given vertices | ||
| all rooted forests | 1, 3, 16, 125, 1296, 16807 | |
| spanning trees of | ||
| functional graphs | ||
| connected functional graphs (one cycle) | 1, 3, 17, 142, 1569, 21576 |
| Unlabelled () | Method | Values |
|---|---|---|
| rooted trees | Euler transform: | 1, 1, 2, 4, 9, 20, 48, 115, 286, 719, 1842 |
| free trees | Otter: | 1, 1, 1, 2, 3, 6, 11, 23, 47, 106, 235 |
| graphs up to isomorphism | Pólya over cycle types (Burnside and Pólya) | 1, 2, 4, 11, 34, 156, … |
struct GraphCounting { // tables for 0..n, prime modulus > n
int n; Comb cb; vector<mint> graphs, connected, dags;
GraphCounting(int N) : n(N), cb(N + 1), graphs(N + 1), connected(N + 1), dags(N + 1) {
for (int i = 0; i <= n; i++) graphs[i] = mint(2).pow((ll)i * (i - 1) / 2);
connected[0] = 0;
for (int i = 1; i <= n; i++) { // fix vertex 1; its component has k vertices
mint s = graphs[i];
for (int k = 1; k < i; k++) s -= cb.C(i - 1, k - 1) * connected[k] * graphs[i - k];
connected[i] = s;
}
dags[0] = 1;
for (int i = 1; i <= n; i++) { // inclusion-exclusion over the set of sources
mint s = 0;
for (int k = 1; k <= i; k++) { mint t = cb.C(i, k) * mint(2).pow((ll)k * (i - k)) * dags[i - k]; s += k % 2 ? t : -t; }
dags[i] = s;
}
}
mint trees(int i) const { return i <= 1 ? mint(1) : mint(i).pow(i - 2); }
mint rootedForests(int i, int k) const { if (k == i) return 1; if (k == 0) return i == 0; return mint(k) * mint(i).pow(i - k - 1); }
mint allRootedForests(int i) const { return mint(i + 1).pow(max(i - 1, 0)); }
mint evenGraphs(int i) const { return i == 0 ? mint(1) : mint(2).pow((ll)(i - 1) * (i - 2) / 2); }
mint connectedFunctional(int i) const {
mint s = 0;
for (int k = 1; k <= i; k++) s += cb.f[i] * cb.fi[i - k] * (k == i ? mint(i).inv() : mint(i).pow(i - k - 1));
return s;
}
mint treesWithDegrees(const vector<int>& d) const { // labelled trees with deg(i) = d[i], n >= 2
int m = sz(d); ll s = 0; for (int x : d) { if (x < 1) return 0; s += x; }
if (s != 2LL * m - 2) return 0;
mint r = cb.f[m - 2]; for (int x : d) r *= cb.fi[x - 1];
return r;
}
};
pair<vector<ll>, vector<ll>> unlabeledTrees(int N) { // r[n] rooted, t[n] free, exact up to n ~ 38
vector<ll> r(N + 1, 0), t(N + 1, 0), s(N + 1, 0); // s[k] = sum_{d | k} d r[d]
if (N >= 1) r[1] = 1;
for (int m = 1; m < N; m++) { // r[m+1] = (1/m) sum_{k=1}^m s[k] r[m-k+1]
for (int d = 1; d <= m; d++) if (m % d == 0) s[m] += d * r[d];
ll acc = 0; for (int k = 1; k <= m; k++) acc += s[k] * r[m - k + 1];
r[m + 1] = acc / m;
}
for (int m = 1; m <= N; m++) {
ll sq = 0; for (int i = 1; i < m; i++) sq += r[i] * r[m - i];
if (m % 2 == 0) sq -= r[m / 2];
t[m] = r[m] - sq / 2;
}
if (N >= 0) t[0] = 1;
return {r, t};
}Complexity: GraphCounting (or with power-series for , Counting with Power Series); unlabeledTrees . Variants solved the same way: connected graphs with edges (DP over vertices and edges with the same “component of vertex 1” split), labelled bipartite and strongly connected digraphs (inclusion–exclusion over a distinguished part, with EGFs).
Proof: the labelled counts
Connected. Fix vertex 1; its component has vertices, chosen in ways, is connected (), and the rest is an arbitrary graph (); summing over gives , solved for the term. As EGFs this says (a graph is a set of connected components). Even graphs: choose any edge set on vertices ; then each vertex is joined to iff its degree so far is odd; vertex ‘s degree is the number of odd-degree vertices of a graph, which is even. This is a bijection. DAGs: every DAG has a non-empty set of sources. For a non-empty set of vertices, the DAGs in which every vertex of is a source are: arbitrary edges from to the rest (), none into , and a DAG on the rest (). Inclusion–exclusion over counts each DAG time.
Trees. Prüfer codes are a bijection between labelled trees on vertices and , in which vertex appears times (Isomorphism and Prüfer): this gives and the multinomial . Rooted forests on given roots: add a new vertex 0 joined to the roots; this is a bijection with the trees on in which 0 has exactly the neighbours . Trees on vertices in which 0 has degree number (0 occupies of the Prüfer positions, the others hold any of the other labels), and by relabelling all neighbour sets of size are equally frequent: . All rooted forests: join a new vertex to every root: a bijection with labelled trees on vertices, . : the Laplacian has eigenvalue on vectors supported on the -side summing to 0 (multiplicity ), symmetrically (), on the vector equal to on the -side and on the -side, and 0 on the constant vector; the Matrix-Tree Theorem gives . Connected functional graphs: the unique cycle has vertices ( cyclic orders), and the other vertices form a forest rooted at the cycle vertices with edges directed towards the roots (, or 1 if ); the product simplifies to .
All labelled counts were checked by brute force over all graphs, digraphs and functions for or 6.
Proof: unlabelled rooted and free trees (Euler transform, Otter)
Rooted. Removing the root leaves a multiset of rooted trees with total size , so . Taking of both sides: with . Multiplying by and comparing the coefficients of : , i.e. , an exact division.
Otter’s dissimilarity. For a tree with automorphism group , let , be the numbers of vertex and edge orbits, and if some automorphism swaps the ends of an edge. Then . Every automorphism fixes the centre. If the centre is a vertex, or an edge whose ends are not swapped, root there: automorphisms preserve parents, so mapping each non-root vertex to the edge to its parent is a bijection between non-root vertex orbits and edge orbits, and . If the centre edge is flipped by some automorphism, map every other edge to its endpoint farther from the centre: this is a bijection between the edge orbits other than and the vertex orbits other than (one orbit), so and . Summing over all trees of size : . The vertex orbits of all trees are the rooted trees (); edge orbits are trees rooted at an edge, i.e. unordered pairs of rooted trees (); flippable centre edges are ordered-identical pairs (). Hence . Both sequences were checked against the known values above (OEIS A000081, A000055).