This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub kmyk/competitive-programming-library
#include "graph/matrix_tree_theorem.hpp"
#pragma once #include <cassert> #include <vector> namespace matrix_tree_theorem { template <class T> T determinant(const std::vector<std::vector<T> >& original_a) { int n = original_a.size(); auto a = original_a; T det = 1; REP (i, n) { REP (j, i) { if (a[j][j] == 0) { int k = j + 1; for (; k < n; ++ k) { if (a[k][j] != 0) break; } if (k == n) return 0; REP3 (l, j, n) { swap(a[j][l], a[k][l]); } } assert (a[j][j] != 0); T t = a[i][j] / a[j][j]; REP3 (k, j + 1, n) { a[i][k] -= a[j][k] * t; } } } REP (i, a.size()) det *= a[i][i]; return det; } template <class T> std::vector<std::vector<T> > small_matrix(const std::vector<std::vector<T> >& a) { int n = a.size(); assert (n >= 1); auto b = a; b.resize(n - 1); REP (y, n - 1) { b[y].resize(n - 1); } return b; } template <class T> std::vector<std::vector<T> > laplacian_matrix_from_adjacency_matrix(const std::vector<std::vector<T> >& a) { REP (y, a.size()) { REP (x, a[y].size()) { if (y == x) { assert (a[y][x] == 0); } } } std::vector<std::vector<T> > l = a; REP (y, l.size()) { REP (x, l[y].size()) { if (y == x) { l[y][y] += l[y][x]; l[y][x] *= -1; } } } return l; } /** * @brief 全域木の個数を数える (行列木定理) * @arg a is an adjacency matrix of a graph without self-loops. Multiple edges are allowed. */ template <class T> T count_spanning_trees(const std::vector<std::vector<T> >& a) { return determinant(small_matrix(laplacian_matrix_from_adjacency_matrix(a))); } }
#line 2 "graph/matrix_tree_theorem.hpp" #include <cassert> #include <vector> namespace matrix_tree_theorem { template <class T> T determinant(const std::vector<std::vector<T> >& original_a) { int n = original_a.size(); auto a = original_a; T det = 1; REP (i, n) { REP (j, i) { if (a[j][j] == 0) { int k = j + 1; for (; k < n; ++ k) { if (a[k][j] != 0) break; } if (k == n) return 0; REP3 (l, j, n) { swap(a[j][l], a[k][l]); } } assert (a[j][j] != 0); T t = a[i][j] / a[j][j]; REP3 (k, j + 1, n) { a[i][k] -= a[j][k] * t; } } } REP (i, a.size()) det *= a[i][i]; return det; } template <class T> std::vector<std::vector<T> > small_matrix(const std::vector<std::vector<T> >& a) { int n = a.size(); assert (n >= 1); auto b = a; b.resize(n - 1); REP (y, n - 1) { b[y].resize(n - 1); } return b; } template <class T> std::vector<std::vector<T> > laplacian_matrix_from_adjacency_matrix(const std::vector<std::vector<T> >& a) { REP (y, a.size()) { REP (x, a[y].size()) { if (y == x) { assert (a[y][x] == 0); } } } std::vector<std::vector<T> > l = a; REP (y, l.size()) { REP (x, l[y].size()) { if (y == x) { l[y][y] += l[y][x]; l[y][x] *= -1; } } } return l; } /** * @brief 全域木の個数を数える (行列木定理) * @arg a is an adjacency matrix of a graph without self-loops. Multiple edges are allowed. */ template <class T> T count_spanning_trees(const std::vector<std::vector<T> >& a) { return determinant(small_matrix(laplacian_matrix_from_adjacency_matrix(a))); } }