矩阵行列式-矩阵树定理-P4111小Z的房间-学习笔记-解题报告-模板
行列式
何为行列式? 一个矩阵对应一个行列式(数字);
行列式有什么用? 目前看来,只有矩阵树定理用上了它;
行列式怎么求?
好博客
简单来说,转置矩阵,行列式不变;
交换两行/列位置,行列式取相反数;
对一行/列乘以某数,行列式也乘以某数;
用一行的倍数减去另一行,行列式的值不变;
一个上三角行列式的值等于对角线的乘积
所以我们可以联想一下高斯消元的做法,把它削成上三角矩阵(注意,不是对角线矩阵),因为在剩余系下没有除法,所以我们要辗转相除;
il int det() {
int ans = 1;
for (ri i = 1; i <= sz; ++i) { // 当前在消第i个(i,i)
for (ri j = i + 1, t; j <= sz; ++j) { // 把它下面对应的位置消成0
while (m[j][i]) { // 直到为0
t = m[i][i] / m[j][i]; // 计算第j行相应的数是第i行的几倍
for (ri k = i; k <= sz; ++k) { // 一个一个消去并交换数字(消去后之前的位置变小)
mod(m[i][k] -= m[j][k] * t);
swap(m[i][k], m[j][k]); // 交换
}
ans *= -1; // 记得交换是,行列式取反
}
}
if (m[i][i] == 0) return 0; // 如果有零,就不用继续做了
else mod(ans *= m[i][i]); // 更新ans
}
return (ans % md + md) % md;
}
牢牢记住
矩阵树定理
(度数矩阵(对角线矩阵)-邻接矩阵)的行列式等于该图生成树个数;
题目总结
矩阵树定理裸题
数据范围
能过
解题思路
如之前所说,直接做;
易错误区
1.!!!要建好图,有的地方不是节点
2.求行列式不要写错,是缩成上三角;
代码展示
//%:pragma GCC optimize(2)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<stack>
#include<bitset>
#include<deque>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define ri register int
#define il inline
#define fi first
#define se second
#define mp make_pair
#define pi pair<int,int>
#define pb push_back
#define mem0(x) memset((x),0,sizeof (x))
#define mem1(x) memset((x),0x3f,sizeof (x))
il char gc() {
static const int BS = 1 << 22;
static unsigned char buf[BS], *st, *ed;
if (st == ed) ed = buf + fread(st = buf, 1, BS, stdin);
return st == ed ? EOF : *st++;
}
#define gc getchar
template<class T>void in(T &x)
{
x = 0; bool f = 0; char c = gc();
while (c < '0' || c > '9') {if (c == '-') f = 1; c = gc();}
while ('0' <= c && c <= '9') {x = (x << 3) + (x << 1) + (c ^ 48); c = gc();}
if (f) x = -x;
}
#undef gc
void out(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
#define int ll
int n, m;
char tc[2];
bool h[12][12];
#define Maxsz 150
#define md 1000000000
il void mod(int &x) {
x = (x % md + md) % md;
}
struct Mat {
int sz;
int m[Maxsz][Maxsz];
il void clear() {mem0(m);}
il Mat () {sz = 0; clear();}
il int* operator[](int x) {
return this->m[x];
}
il Mat operator*(const Mat &x)const {
Mat res; res.sz = sz;
for (ri i = 1; i <= sz; i++) {
for (ri k = 1; k <= sz; k++) {
for (ri j = 1; j <= sz; j++)
mod(res.m[i][j] += m[i][k] * x.m[k][j] % md);
}
}
return res;
}
il void operator*=(const Mat &x) {
*this = (*this) * x;
}
il void operator+=(const Mat &x) {
for (ri i = 1; i <= sz; ++i) {
for (ri j = 1; j <= sz; ++j) {
mod(m[i][j] += x.m[i][j]);
}
}
}
il Mat operator+(const Mat &x)const {
Mat res = *this;
res += x;
return res;
}
il void operator-=(const Mat &x) {
for (ri i = 1; i <= sz; ++i) {
for (ri j = 1; j <= sz; ++j) {
m[i][j] -= x.m[i][j];//mod(m[i][j] -= x.m[i][j]);
}
}
}
il Mat operator-(const Mat &x)const {
Mat res = *this;
res -= x;
return res;
}
il void print() {
for (ri i = 1; i <= sz; i++) {
for (ri j = 1; j <= sz; j++)
printf("%lld ", m[i][j]);
puts("");
}
}
il void e() {
clear();
for (ri i = 1; i <= sz; i++)
m[i][i] = 1;
}
il Mat qpow(int x) {
Mat res, mul = *this;
if (x == 0) {
res.e();
return res;
}
res = *this; --x;
for (; x; x >>= 1, mul *= mul) if (x & 1) res *= mul;
return res;
}
il int det() {
int ans = 1;
for (ri i = 1; i <= sz; ++i) {
for (ri j = i + 1, t; j <= sz; ++j) {
while (m[j][i]) {
t = m[i][i] / m[j][i];
for (ri k = i; k <= sz; ++k) {
mod(m[i][k] -= m[j][k] * t);
swap(m[i][k], m[j][k]);
}
ans *= -1;
}
}
if (m[i][i] == 0) return 0;
else mod(ans *= m[i][i]);
}
return (ans % md + md) % md;
}
} d, g, s;
int cnt;
int xx[4] = {0, 1, 0, -1}, yy[4] = { -1, 0, 1, 0};
il bool check(int x, int y) {
return (x >= 1) && (y >= 1) && (x <= n) && (y <= m) && (h[x][y] == 1);
}
signed main() {
in(n), in(m);
for (ri i = 1; i <= n; ++i) {
for (ri j = 1; j <= m; ++j) {
scanf("%1s", tc);
h[i][j] = (tc[0] == '.');
}
}
for (ri i = 1; i <= n; ++i) {
for (ri j = 1; j <= m; ++j) {
if (h[i][j]) {
s[i][j] = ++cnt;
if (check(i, j - 1)) {
g[s[i][j]][s[i][j - 1]] = 1;
g[s[i][j - 1]][s[i][j]] = 1;
}
if (check(i - 1, j)) {
g[s[i][j]][s[i - 1][j]] = 1;
g[s[i - 1][j]][s[i][j]] = 1;
}
}
}
}
for (ri i = 1; i <= cnt; ++i) {
for (ri j = 1; j <= cnt; ++j) {
if (g[i][j])
d[i][i]++;
}
}
d.sz = g.sz = cnt;
d -= g; --d.sz;
printf("%lld", d.det());
return 0;
}