给n个点m条边的图,求该图的最小生成树个数。
我们对这个图构造两个矩阵,分别是这个图的连通矩阵和度数矩阵。连通矩阵 S 1 S1 S1的第 i i i行第 j j j列上的数字表示原无向图中编号为 i i i和编号为 j j j的两个点之间的边的条数。度数矩阵 S 2 S2 S2只有斜对角线上有数字,即只有第 i i i行第 i i i列上有数字,表示编号为i的点的度数是多少。我们将两个矩阵相减,即 S 2 − S 1 S2−S1 S2−S1,我们记得到的矩阵为 T T T,我们将矩阵 T T T去掉任意一行和一列(一般情况去掉最后一行和最后一列的写法比较多)得到 T ′ T^′ T′,最后生成树的个数就是这个矩阵 T ′ T^′ T′的行列式。
——摘自:《矩阵树定理浅谈》
定义:如果图 D D D有总共 N N N个点,那么图 D D D的基尔霍夫矩阵 G G G可以表示为:
G i j = { d e g r e e ( i ) i = j − c n t ( i , j ) i ≠ j G_{ij}=\left\{ \begin{array}{rcl} & degree(i) & &{i=j}\\ &−cnt(i,j) & &{i \neq j}\\ \end{array}\right. Gij={ degree(i)−cnt(i,j)i=ji=j
d e g r e e degree degree:结点i的度数
c n t cnt cnt :两点之间的边数
解决问题的关键就是利用基尔霍夫矩阵。
以下假设图无重边,证明摘自:《生成树的计数及其应用》周冬
证明:假设图 D D D有 k ( k > 1 ) k(k>1) k(k>1)个连通份量 D 1 , D 2 , . . . , D k D_1,D_2,...,D_k D1,D2,...,Dk。我们可以通过矩阵的变换使得这些连通分量的排列如下:(每次变换行列都交换一次,对应行列式符号不变)
( D 1 0 ⋯ 0 0 D 2 ⋯ 0 ⋮ ⋮ ⋱ ⋮ 0 0 0 D k ) \begin{pmatrix} D_1 & 0 &\cdots& 0\\\\ 0 & D_2 &\cdots&0\\\\ \vdots &\vdots & \ddots&\vdots\\\\ 0 & 0 & 0 &D_k\\\\ \end{pmatrix} ⎝⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎛D10⋮00D2⋮0⋯⋯⋱000⋮Dk⎠⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎞(矩阵中的0元素确保连通分量之间不连通)
∣ G ∣ \left|G\right| ∣G∣= ∣ G 1 ∣ \left|G_1\right| ∣G1∣ ∣ G 2 ∣ ⋯ ∣ G k ∣ \left|G_2\right|\cdots\left|G_k\right| ∣G2∣⋯∣Gk∣,据此可得出对应基尔霍夫矩阵的任意 n − 1 n-1 n−1阶主子式为0。
引入定义,矩阵 B B B为 n × m n\times m n×m矩阵,分别对应结点和边。
B i j = { − 1 v i 为 边 e j 起 点 1 v i 为 边 e j 终 点 0 o t h e r w i s e B_{ij}=\left\{ \begin{array}{rcl} & -1 & &v_i为边e_j起点\\ &1 & &v_i为边e_j终点\\ &0 & &otherwise\\ \end{array}\right. Bij=⎩⎨⎧−110vi为边ej起点vi为边ej终点otherwise
容易验证: B B T = G BB^T=G BBT=G,若去掉 B B B中第 r r r行得到 B r B_r Br,有 G r = B r B r T G_r=B_rB_r^T Gr=BrBrT,即 G G G去掉第 r r r行和第 r r r列。
看一下Binet-Cauchy公式:
设矩阵 A A A为 p × q p\times q p×q矩阵,矩阵 B B B为 q × p q\times p q×p矩阵,有
d e t ( A B ) = { 0 当 p > q 时 d e t ( A ) d e t ( B ) 当 p = q 时 ∑ 1 ≤ j 1 < j 2 < ⋯ < j p ≤ q A ( 1 2 ⋯ p j 1 j 2 ⋯ j p ) B ( j 1 j 2 ⋯ j p 1 2 ⋯ p ) 当 p < q 时 det(AB)=\left\{ \begin{array}{rcl} &0& 当p>q时\\ &det(A)det(B)& 当p=q时\\ & \sum\limits_{1\leq j_1<j_2<\cdots<j_p\leq q} A\begin{pmatrix} 1 &2&\cdots&p\\\\ j_1&j_2&\cdots&j_p \end{pmatrix} B\begin{pmatrix} j_1&j_2&\cdots&j_p\\\\ 1&2&\cdots&p \end{pmatrix} &当p<q时\\ \end{array}\right. det(AB)=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧0det(A)det(B)1≤j1<j2<⋯<jp≤q∑A⎝⎛1j12j2⋯⋯pjp⎠⎞B⎝⎛j11j22⋯⋯jpp⎠⎞当p>q时当p=q时当p<q时
其中 A ( 1 2 ⋯ p j 1 j 2 ⋯ j p ) A\begin{pmatrix} 1 &2&\cdots&p\\\\ j_1&j_2&\cdots&j_p \end{pmatrix} A⎝⎛1j12j2⋯⋯pjp⎠⎞表示 A A A的第 j 1 , j 2 , . . . , j p j_1,j_2,...,j_p j1,j2,...,jp列所成的子式, B ( j 1 j 2 ⋯ j p 1 2 ⋯ p ) B\begin{pmatrix} j_1&j_2&\cdots&j_p\\\\ 1&2&\cdots&p \end{pmatrix} B⎝⎛j11j22⋯⋯jpp⎠⎞表示 B B B的第 j 1 , j 2 , . . . , j p j_1,j_2,...,j_p j1,j2,...,jp行所成的子式。
从而得到:
d e t ( G r ) = d e t ( B r B r T ) = ∑ x ⊂ { 1 , 2 , . . , m } ∣ x ∣ = n − 1 d e t ( B r x B r x T ) = ∑ x ⊂ { 1 , 2 , . . , m } ∣ x ∣ = n − 1 ( d e t ( B r x ) ) 2 det(G_r)=det(B_rB_r^T)=\sum\limits_{x\subset \{1,2,..,m\}\atop\left|x\right|=n-1}det(B_r^xB_r^{x^T})=\sum\limits_{x\subset \{1,2,..,m\}\atop\left|x\right|=n-1}(det(B_r^x))^2 det(Gr)=det(BrBrT)=∣x∣=n−1x⊂{ 1,2,..,m}∑det(BrxBrxT)=∣x∣=n−1x⊂{ 1,2,..,m}∑(det(Brx))2
解释一下: B r B_r Br为 ( n − 1 ) × m (n-1)\times m (n−1)×m矩阵( m > n − 1 m>n-1 m>n−1),则 d e t ( B r B r T ) = det(B_rB_r^T)= det(BrBrT)=所有 n − 1 n-1 n−1列构成的子式的行列式的平方和。
B r x B_r^x Brx表示 B r B_r Br中边元素属于包含于边集 E E E的子集 x x x的所在列抽出构成的新矩阵,显然 B r x B r x T B_r^xB_r^{x^T} BrxBrxT可以看作一个 n n n个点和 n − 1 n-1 n−1条边构成的图的基尔霍夫矩阵的的一个 n − 1 n-1 n−1阶主子式,当 x x x为树时,行列式值为1,否则图不连通值为0,考察所有边集元素个数为 n − 1 n-1 n−1的子集,结果就恰好为生成树个数!
对于含重边的图该定理仍然适用,但是如何证明尚且不知…
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod = 1e9;
const int dir[4][2] = {
{
1,0},{
0,1}};
int n, m;
char g[10][10];
ll K[100][100];
int id[10][10];
void update(int x, int y) {
K[x][y]--; K[y][x]--;
K[x][x]++; K[y][y]++;
}
ll det(int n) {
ll res = 1;
for (int i = 1; i <= n; i++) {
//依次把第i列,从第i+1行到第n行变为0
for (int j = i + 1; j <= n; j++) {
while (K[j][i]) {
//直到为0
ll t = K[i][i] / K[j][i];//计算第i列,第i行是第j行的几倍
for (int k = i; k <= n; k++) {
K[i][k] = (K[i][k] - t * K[j][k] % mod + mod) % mod;
swap(K[i][k], K[j][k]);//把第i行元素变为0后与第j行交换
}
res = -res;//每次交换行 值变为原来的负数
}
}
if (!K[i][i])return 0;
res = (res * K[i][i] % mod + mod) % mod;//将行列式化为上三角行列式后 值为对角线元素的乘积
}
return res;
}
char read() {
char ch = getchar();
while (ch != '.' && ch != '*')ch = getchar();
return ch;
}
int main(void) {
memset(K, 0, sizeof(K));
memset(id, 0, sizeof(id));
scanf("%d %d", &n, &m);
int cnt = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
g[i][j] = read();
if (g[i][j] == '.')id[i][j] = ++cnt;
}
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (g[i][j] == '.') {
if (id[i - 1][j])update(id[i - 1][j], id[i][j]);
if (id[i][j - 1])update(id[i][j - 1], id[i][j]);
}
printf("%lld\n", det(cnt - 1) % mod);
return 0;
}
文章浏览阅读1.7k次。可以看到很多联发科的MT芯片摘自:https://net.zol.com.cn/531/5312999.html彻底扒光 通过智能路由器拆解看其本质2015-07-23 00:40:00[中关村在线 原创] 作者:陈赫|责编:白宁收藏文章 分享到 评论(24)关注智能路由器拆解的朋友们注意啦!我们已经将这五款产品彻底扒开,将主板的真容展现在了大家的眼前。网友们可以看见这些智能路由器主板的做工和用料,我们还为网友们展示了主要的电子元器件,供大家品评观赏。..._路由器拆解
文章浏览阅读2.1k次,点赞101次,收藏78次。【学习背景】今天主要是来了解Java线程Thread中的run()、start()两个方法的执行有哪些区别,会给出一个简单的测试代码样例,快速理解两者的区别,再从源码层面去追溯start()底层是如何最终调用Thread#run()方法的,个人觉得这样的学习不论对面试,还是实际编程来说都是比较有帮助的。进入正文~学习目录一、代码测试二、源码分析2.1 run()方法2.2 start()方法三、使用总结一、代码测试执行Thread的run()、start()方法的测试代码如下:public_jdk的源码hotspot跟jdk是分开的
文章浏览阅读4.4k次,点赞90次,收藏85次。俄乌冲突中,各方势力通过数据擦除恶意软件破坏关键信息基础设施计算机的数据,达到深度致瘫的效果,同时窃取重要敏感信息。_俄乌网络战观察(一)
文章浏览阅读1.7w次,点赞23次,收藏139次。Maven 私服是一种特殊的Maven远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的远程仓库(中央仓库、其他远程公共仓库)。当然也并不是说私服只能建立在局域网,也有很多公司会直接把私服部署到公网,具体还是得看公司业务的性质是否是保密的等等,因为局域网的话只能在公司用,部署到公网的话员工在家里也可以办公使用。_nexus maven
文章浏览阅读934次。我先用所有的样本数据对模型做几轮初步训练,让深度神经模型基本拟合(数万条记录的训练集,识别率到99%左右),具备初步的识别能力,这时的模型就是“直男”。相较于训练很多轮、拟合程度很高的“油腻男”,它的拟合程度较低,还是“直男愣头青”。..............._java ocr ai识别训练
文章浏览阅读688次。一、问题现象: 在数据库表中日期字段中存的日期光有年月日,没有时分秒。二、产生原因:三 解决办法 检查表的相应映射xml文件。 <property name="operateDate" type="Date">如果同上面所写,那问题出在 type类型上了正确写法 :<property name="operateDate" type="java.util..._hibernate解析時間只有年月日沒有時分秒
文章浏览阅读1k次,点赞2次,收藏2次。文章目录问题描述:解决方案:问题描述:提示:idea springbbot运行无法编译成功,找不到jar包报错E:\ideaProject\demokkkk\src\main\java\com\example\demo\config\WebSocketConfig.javaError:(3, 46) java: 程序包org.springframework.context.annotation不存在Error:(4, 46) java: 程序包org.springframework.conte_error:(3, 46) java: 程序包org.springframework.context.annotation不存在
文章浏览阅读6.4k次,点赞6次,收藏36次。1、redux中间件中间件提供第三方插件的模式,自定义拦截 action -> reducer 的过程。变为 action -> middlewares -> reducer 。这种机制可以让我们改变数据流,实现如异步 action ,action 过滤,日志输出,异常报告等功能。常见的中间件:redux-logger:提供日志输出redux-thunk:处理异步操作..._recate面试
文章浏览阅读405次。由于要在开发板中加载libjpeg,不能使用gcc编译的库文件给以使用,需要自己配置使用另外的编译器编译该库文件。/usr/bin/ld:.libs/jaricom.o:RelocationsingenericELF(EM:40)/usr/bin/ld:.libs/jaricom.o:RelocationsingenericELF(EM:40)...._jpeg_utils.lo: relocations in generic elf (em: 8) error adding symbols: file
文章浏览阅读578次,点赞10次,收藏17次。【办公类-22-06】周计划系列(1)“信息窗” (2024年调整版本)
文章浏览阅读309次。SEO全称为Search Engine Optimization,中文解释为搜索引擎优化。一般指通过对网站内部调整优化及站外优化,使网站满足搜索引擎收录排名需求,在搜索引擎中提高关键词排名,从而把精准..._百度seo resetful
文章浏览阅读438次。回归预测 | Matlab实现HPO-ELM猎食者算法优化极限学习机的数据回归预测_猎食者优化算法