行列式与matrix_tree

目录

相关资料:

Matrix-Tree定理和模意义下的矩阵行列式:

行列式:

自己的理解:

(1)n阶行列式定义:

(2)行列式相关拓展:

(3)行列式性质

题目链接:【CQOI2018】社交网络

[End]


相关资料:

Matrix-Tree定理和模意义下的矩阵行列式:

Matrix-Tree定理和模意义下的矩阵行列式_determinant的博客-CSDN博客
 

行列式:

百度文库

行列式_martinzrx的博客-CSDN博客_行列式


自己的理解:

(1)n阶行列式定义:

其中,“ j1j2···jn ” 为n级全排列。

ps: 逆序数即为该数列中每一项前面比它大的数的个数之和。

更一般的:


(2)行列式相关拓展:

特殊行列式:

练习一下计算行列式吧:

(1)

(2)


(3)行列式性质

  1. 交换任意两行(列),行列式变号。
  2. 把某一行(列)乘上一个常数,行列式也乘上该常数。
  3. 把一行(列)乘上一个常数加到另一行(列)上,行列式不变
  4. 若矩阵中某一行(列)全为0,则行列式为0。

题目链接:【CQOI2018】社交网络

做法: 对于一个有向图,我们构造如下 A 矩阵:(其中 a[i][j] 表示矩阵第 i 行第 j 列的元素) 对于 i != j, a[i][j] 为 i 到 j 的边数的相反数; a[i][i] 为 i 的出度。
(Matrix_tree定理)

对于无向图,a[i][j] 为 i 与 j 之间边数的相反数,a[i][i] 为度数
对于有向图,a[i][j] 为 i 到 j 的边数的相反数,a[i][i] 为出度

那么这个矩阵删去第 1 行第 1 列之后的行列式为以 1 号点为根的树形图的数量。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 300, mod = 10007;
int a[maxn][maxn], n;
int ksm(int x,int k)   // 快速幂
{
	int ans=1;
	while(k)
	{
		if(k & 1) ans = ans*x%mod;
		x = x*x%mod;
		k >>= 1;
	}
	return ans;
}
int hls() // 就是把行列式化成上三角行列式,然后求出主对称轴的乘积,即为行列式的值 
{
	int now=1, ans=1; // 交换行次数导致乘的数,answer
	for(int i = 2; i <= n; ++i)   // 此题不计算1行1列
	{
		int pos = i;
		for(; pos <= n; ++pos) if(a[pos][i]) break; // 找到第一行i列不为0,交换(为了消元)
		if(pos != i)   // 自己不为0就不用换
		{
			now *= -1;
			swap(a[i], a[pos]);
		}
		if(!a[i][i]) return 0; // i列全都为0就返回0(hls性质4)
		ans = ans*a[i][i]%mod; // 更新答案
		int inv = ksm(a[i][i],mod-2); // 消元 
		for(int j = i + 1; j <= n; ++j)   // 将下面所有行i列消成0
		{
			if(!a[j][i]) continue; // 本来就是0就不用消了
			int mul = a[j][i]*inv % mod; // 计算由i行消j行需要乘的数 
			for(int k = 2; k <= n; ++k)
				a[j][k] = (a[j][k]-a[i][k]*mul)%mod;
		}
	}
	ans = ans*now;
	return (ans+mod)%mod; // 负数情况转正数
}
int main()
{
	ios::sync_with_stdio(false); cin.tie(NULL);
	int m, v, u;
	cin >> n >> m;
	for(int i = 1; i <= m; ++i)
	{
		cin >> v >> u; // u->v
		a[v][v]++; a[v][u]--;
	}
	for(int i = 1; i <= n; ++i)
	{
		for(int j = 1; j <= n; ++j)
		{
			if(a[i][j] < 0) a[i][j] += mod; // 防止取模出现问题 
		}
	}
	cout << hls();
	return 0;
}

[End]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值