This documentation is automatically generated by online-judge-tools/verification-helper
#include "Graph/countspanning.hpp"
#pragma once #include "Math/matrix.hpp" template <typename T, typename U> T UndirectedCountSpanningTree(vector<vector<pair<int, U>>> &g) { int n = SZ(g); Matrix<T> mat(n - 1, n - 1); rep(u, 0, n) for (auto &[v, mul] : g[u]) { if (u != n - 1) mat[u][u] += mul; if (v != n - 1) mat[v][v] += mul; if (u != n - 1 and v != n - 1) { mat[u][v] -= mul; mat[v][u] -= mul; } } mat.gauss(); return mat.det; } template <typename T, typename U> T DirectedCountSpanningTree(vector<vector<pair<int, U>>> &g, int r) { int n = SZ(g); Matrix<T> mat(n - 1, n - 1); rep(u, 0, n) for (auto &[v, mul] : g[u]) { if (v == r) continue; if (v > r) v--; mat[v][v] += mul; if (u == r) continue; if (u > r) u--; mat[u][v] -= mul; } mat.gauss(); return mat.det; } /** * @brief Counting Spanning Tree */
#line 2 "Math/matrix.hpp" template <class T> struct Matrix { int h, w; vector<vector<T>> val; T det; Matrix() {} Matrix(int n) : h(n), w(n), val(vector<vector<T>>(n, vector<T>(n))) {} Matrix(int n, int m) : h(n), w(m), val(vector<vector<T>>(n, vector<T>(m))) {} vector<T> &operator[](const int i) { return val[i]; } Matrix &operator+=(const Matrix &m) { assert(h == m.h and w == m.w); rep(i, 0, h) rep(j, 0, w) val[i][j] += m.val[i][j]; return *this; } Matrix &operator-=(const Matrix &m) { assert(h == m.h and w == m.w); rep(i, 0, h) rep(j, 0, w) val[i][j] -= m.val[i][j]; return *this; } Matrix &operator*=(const Matrix &m) { assert(w == m.h); Matrix<T> res(h, m.w); rep(i, 0, h) rep(j, 0, m.w) rep(k, 0, w) res.val[i][j] += val[i][k] * m.val[k][j]; *this = res; return *this; } Matrix operator+(const Matrix &m) const { return Matrix(*this) += m; } Matrix operator-(const Matrix &m) const { return Matrix(*this) -= m; } Matrix operator*(const Matrix &m) const { return Matrix(*this) *= m; } Matrix pow(ll k) { Matrix<T> res(h, h), c = *this; rep(i, 0, h) res.val[i][i] = 1; while (k) { if (k & 1) res *= c; c *= c; k >>= 1; } return res; } vector<int> gauss(int c = -1) { det = 1; if (val.empty()) return {}; if (c == -1) c = w; int cur = 0; vector<int> res; rep(i, 0, c) { if (cur == h) break; rep(j, cur, h) if (val[j][i] != 0) { swap(val[cur], val[j]); if (cur != j) det *= -1; break; } det *= val[cur][i]; if (val[cur][i] == 0) continue; rep(j, 0, h) if (j != cur) { T z = val[j][i] / val[cur][i]; rep(k, i, w) val[j][k] -= val[cur][k] * z; } res.push_back(i); cur++; } return res; } Matrix inv() { assert(h == w); Matrix base(h, h * 2), res(h, h); rep(i, 0, h) rep(j, 0, h) base[i][j] = val[i][j]; rep(i, 0, h) base[i][h + i] = 1; base.gauss(h); det = base.det; rep(i, 0, h) rep(j, 0, h) res[i][j] = base[i][h + j] / base[i][i]; return res; } bool operator==(const Matrix &m) { assert(h == m.h and w == m.w); rep(i, 0, h) rep(j, 0, w) if (val[i][j] != m.val[i][j]) return false; return true; } bool operator!=(const Matrix &m) { assert(h == m.h and w == m.w); rep(i, 0, h) rep(j, 0, w) if (val[i][j] == m.val[i][j]) return false; return true; } friend istream &operator>>(istream &is, Matrix &m) { rep(i, 0, m.h) rep(j, 0, m.w) is >> m[i][j]; return is; } friend ostream &operator<<(ostream &os, Matrix &m) { rep(i, 0, m.h) { rep(j, 0, m.w) os << m[i][j] << (j == m.w - 1 and i != m.h - 1 ? '\n' : ' '); } return os; } }; /** * @brief Matrix */ #line 3 "Graph/countspanning.hpp" template <typename T, typename U> T UndirectedCountSpanningTree(vector<vector<pair<int, U>>> &g) { int n = SZ(g); Matrix<T> mat(n - 1, n - 1); rep(u, 0, n) for (auto &[v, mul] : g[u]) { if (u != n - 1) mat[u][u] += mul; if (v != n - 1) mat[v][v] += mul; if (u != n - 1 and v != n - 1) { mat[u][v] -= mul; mat[v][u] -= mul; } } mat.gauss(); return mat.det; } template <typename T, typename U> T DirectedCountSpanningTree(vector<vector<pair<int, U>>> &g, int r) { int n = SZ(g); Matrix<T> mat(n - 1, n - 1); rep(u, 0, n) for (auto &[v, mul] : g[u]) { if (v == r) continue; if (v > r) v--; mat[v][v] += mul; if (u == r) continue; if (u > r) u--; mat[u][v] -= mul; } mat.gauss(); return mat.det; } /** * @brief Counting Spanning Tree */