## 问题描述

  给你一个图(有向无向都ok),求这个图的生成树个数

  

一些概念

  度数矩阵:\(a[i][i]=degree[i]\),其他等于\(0\)

  入度矩阵:\(a[i][i]=in\_degree[i]\),其他等于\(0\)

  出度矩阵:\(a[i][i]=out\_ degree[i]\),其他等于\(0\)

  邻接矩阵:\(边集a[i][j]=[(i,j)\in 边集]\)

  基尔霍夫矩阵:度数矩阵-邻接矩阵

  

  外向树:长成树的样子但是边有方向,方向为根-->叶子

  外向树:长成树的样子但是边有方向,方向为叶子-->根

  

前置技能

行列式

  因为接下来可能需要用到行列式中的某些概念所以还是简单讲一下吧(额只挑部分来讲毕竟我比较菜qwq)

  上三角矩阵:就是。。只有主对角线及其上方的位置有值的行列式,主对角线以下的部分都是\(0\)

  行列式的求值:我们可以先用高斯消元把这个行列式消成一个上三角矩阵的形式然后直接把对角线上的数乘起来得到这个行列式的值

  余子式:一个行列式的余子式就是这个行列式去掉任意一行一列后剩下的那个少了一维的行列式

  

具体内容

无向图的生成树计数

  无向图的话生成树个数就是这个图的基尔霍夫矩阵的任意一个余子式的行列式值

有向图的生成树计数

​  有向图的话分成两种情况:

​  1、求外向树:那么将无向图中的度数矩阵改成入度矩阵

​  2、求内向树:将无向图种的度数矩阵改成出度矩阵

​  不过需要特别注意的一点是:有向图的话余子式去掉的行、列必须是根节点对应的那个

(是不是特别特别简洁明了ovo)

​  p.s.其实在有重边的情况下这个也是成立的只不过在邻接矩阵那里有多少条边就要加多少而不是单纯是\(1\)

  

证明

​  这是一个要慢慢填的坑。。。

  

例题

  这里放一道模板题好了,另外还有几道相对来说貌似也是挺裸的,会在最后提供传送门这里就不贴详细啦

Portal-->bzoj4031小z的房间

  需要稍微注意一下的是,对于不能去的房间,要直接整个房间删掉(因为根本就不在连通的考虑范围内),还有就是注意这个模数不是质数所以要辗转相除一下(其实就是高消那里换成不为\(0\)就一直除除除除除就好了嗯)

  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int N=110,MOD=1e9;
const int dx[2]={-1,0},dy[2]={0,1};
ll a[N][N],rec[N][N],id[N][N];
char mp[N][N];
int n,m,ans,cnt;
void prework();
int solve(int n);
bool ok(int x,int y); int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
scanf("%d%d\n",&n,&m);
for (int i=1;i<=n;++i){
for (int j=1;j<=m;++j)
scanf("%c",&mp[i][j]);
scanf("\n");
}
prework();
ans=solve(cnt-1);
printf("%d\n",ans);
} void prework(){
int x,y,id1,id2;
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
if (mp[i][j]=='.') id[i][j]=++cnt;
for (int i=1;i<=n;++i){
for (int j=1;j<=m;++j){
if (!ok(i,j)) continue;
id1=id[i][j];
for (int k=0;k<2;++k){
x=i+dx[k]; y=j+dy[k];
if (!ok(x,y)) continue;
id2=id[x][y];
++a[id1][id1]; ++a[id2][id2];
--a[id1][id2]; --a[id2][id1];
}
}
}
} bool ok(int x,int y){
if (x<1||x>n||y<1||y>m) return false;
if (mp[x][y]=='*') return false;
return true;
} int solve(int n){
int id,mark=1;
int tmp;
for (int i=1;i<=n;++i){
id=i;
for (int j=i+1;j<=n;++j)
if (a[j][i]){id=j;break;}
if (id!=i){
mark=-mark;
for (int j=1;j<=n;++j) swap(a[id][j],a[i][j]);
}
for (int j=i+1;j<=n;++j){
while (a[j][i]){
tmp=a[j][i]/a[i][i];
for (int k=1;k<=n;++k)
a[j][k]=(1LL*a[j][k]+MOD-1LL*tmp*a[i][k]%MOD)%MOD;
if (a[j][i]==0) break;
mark=-mark;
for (int k=1;k<=n;++k)
swap(a[j][k],a[i][k]);
}
}
}
int ret=mark;
for (int i=1;i<=n;++i)
ret=1LL*ret*a[i][i]%MOD;
return (ret+MOD)%MOD;
}

  

  

  其他的一些题目(是blog的传送门哦,题面传送门的话在blog里面也有)

Portal-->bzoj4894天赋

Portal-->bzoj1002轮状病毒(这题很假对这题很假)

Portal-->bzoj4596黑暗前的幻想乡

【learning】矩阵树定理的更多相关文章

  1. 【Learning】矩阵树定理 Matrix-Tree

    矩阵树定理 Matrix Tree ​ 矩阵树定理主要用于图的生成树计数. 看到给出图求生成树的这类问题就大概要往这方面想了. 算法会根据图构造出一个特殊的基尔霍夫矩阵\(A\),接着根据矩阵树定理, ...

  2. [spoj104][Highways] (生成树计数+矩阵树定理+高斯消元)

    In some countries building highways takes a lot of time... Maybe that's because there are many possi ...

  3. BZOJ 4766: 文艺计算姬 [矩阵树定理 快速乘]

    传送门 题意: 给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图$K_{n,m}$ 求生成树个数 1 <= n,m,p <= 10^18 显然不能暴力上矩阵树定理 看 ...

  4. bzoj 4596 [Shoi2016]黑暗前的幻想乡 矩阵树定理+容斥

    4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 559  Solved: 325[Submit][Sta ...

  5. 【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)

    [LOJ#6072]苹果树(矩阵树定理,折半搜索,容斥) 题面 LOJ 题解 emmmm,这题似乎猫讲过一次... 显然先\(meet-in-the-middle\)搜索一下对于每个有用的苹果数量,满 ...

  6. 2019.01.02 bzoj2467: [中山市选2010]生成树(矩阵树定理)

    传送门 矩阵树定理模板题. 题意简述:自己看题面吧太简单懒得写了 直接构建出这4n4n4n个点然后按照题面连边之后跑矩阵树即可. 代码: #include<bits/stdc++.h> # ...

  7. [CF917D]Stranger Trees[矩阵树定理+解线性方程组]

    题意 给你 \(n\) 个点的无向完全图,指定一棵树 \(S\),问有多少棵生成树和这棵树的公共边数量为 \(k\in[0,n-1]\) \(n\leq 100\) 分析 考虑矩阵树定理,把对应的树边 ...

  8. 【bzoj4596】[Shoi2016]黑暗前的幻想乡 容斥原理+矩阵树定理

    题目描述 给出 $n$ 个点和 $n-1$ 种颜色,每种颜色有若干条边.求这张图多少棵每种颜色的边都出现过的生成树,答案对 $10^9+7$ 取模. 输入 第一行包含一个正整数 N(N<=17) ...

  9. 【BZOJ5133】[CodePlus2017年12月]白金元首与独舞 矩阵树定理

    [BZOJ5133][CodePlus2017年12月]白金元首与独舞 题面:www.lydsy.com/JudgeOnline/upload/201712/div1.pdf 题解:由于k很小,考虑用 ...

  10. CSU 1805 Three Capitals(矩阵树定理+Best定理)

    http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1805 题意: A和B之间有a条边,A和G之间有b条边,B和G之间有c条边.现在从A点出发走遍所 ...

随机推荐

  1. 虚拟货币——比特币行情价格分析

    最近挖以太币的朋友们在关注以太坊行情时,一定会发现以太币的价格对比之前上涨了不少.肯定有部分朋友想了解这次上涨的原因,我们特地为此查询了一番.因为比特币相当于虚拟货币中的黄金,它的价格波动会波及到其他 ...

  2. 445. Cosine Similarity【LintCode java】

    Description Cosine similarity is a measure of similarity between two vectors of an inner product spa ...

  3. linux云主机小技巧

    微信服务器安装 安装库 python 3.5环境下 pip安装web.py时 会报错 "no module named "utils" 等问题 更换命令为“pip ins ...

  4. python循环结构

    while循环 while 条件表达式: 语句块 while语句的条件表达式是循环条件,常用的是关系表达式或者逻辑表达式,语句块是循环执行的语句. n=1 p=1 num=int(input(&quo ...

  5. npm 常用指令

    npm install <name>安装nodejs的依赖包 例如npm install express 就会默认安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本, ...

  6. HDU 1754 I Hate It 线段树(单点更新,成段查询)

    题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=1754 题解: 单点更新,成段查询. 代码: #include<iostream> ...

  7. lintcode-394-硬币排成线

    394-硬币排成线 有 n 个硬币排成一条线.两个参赛者轮流从右边依次拿走 1 或 2 个硬币,直到没有硬币为止.拿到最后一枚硬币的人获胜. 请判定 第一个玩家 是输还是赢? 样例 n = 1, 返回 ...

  8. 操作系统cmd

    实验一  命令解释程序的编写(两周内) 一.目的和要求 1. 实验目的 (1)掌握命令解释程序的原理: (2)*掌握简单的DOS调用方法: (3)掌握C语言编程初步. 2.实验要求 编写类似于DOS, ...

  9. Beta阶段冲刺第二天

    提供当天站立式会议照片一张 讨论项目每个成员的昨天进展 错题集功能编写没有彻底完成. 界面改善 测试数据库连接 讨论项目每个成员的存在问题 邹其元:错题集功能需要用到数据库,现在要解决的问题是怎样把数 ...

  10. Maven编译打包出错:找不到符号

    项目中,使用的是maven管理,但是有几个jar不是通过maven引入的,是通过IDEA导入的,在使用maven插件编译的时候,会出现如下的一些错误: 解决方法: 在项目中创建一个目录lib,然后将j ...