## 问题描述

  给你一个图(有向无向都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. 获取一个数组里面第K大的元素

    如何在O(n)内获取一个数组比如{9, 1, 2, 8, 7, 3, 6, 4, 3, 5, 0, 9, 19, 39, 25, 34, 17, 24, 23, 34, 20}里面第K大的元素呢? 我 ...

  2. hdu - 6282,2018CCPC湖南全国邀请赛G题,字符串,规律

    HDU – 6282 http://acm.hdu.edu.cn/showproblem.php?pid=6282 by Hzu_Tested 题意:给出两个字符串S和T,只由a,b,c三种字符组成( ...

  3. 228. [LeetCode] Summary Ranges

    Given a sorted integer array without duplicates, return the summary of its ranges. Example 1: Input: ...

  4. gopherjs

    An example implementation of a GopherJS client and a Go server using the Improbable gRPC-Web impleme ...

  5. 无法找到 ContextLoaderListener 类

    问题:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener 原因:Eclips ...

  6. 工作在Amazon:为何晋升如此难?

    英文原文:Why It's So Difficult to Climb Amazon's Corporate Ladder 本文作者 Brad Stone 的新书 The Everything Sto ...

  7. 2.openldap安装

    1.安装步骤如下 获取软件包 安装软件包(rpm或者源码编译) 生产openldap配置文件及数据库文件 配置 添加目录树条目 加载slapd进程 验证 2.所需安装包说明 openldap,open ...

  8. TCP半开连接与半闭连接

    半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Duplex)协议,因此这里的半连接"半"字就是相对于全双工的"全&q ...

  9. 如何开发一个 PyCharm 插件

    PyCharm 是很多 Python 开发者优先选择的 IDE,功能强大,跨平台,提供免费社区版,非常良心.如果你想自己给PyCharm添加一些功能怎么办呢?有两个办法: 通过提需求实现,到 JetB ...

  10. Python常用模块之hashlib

    Python里面的hashlib模块提供了很多加密的算法,这里介绍一下hashlib的简单使用事例,用hashlib的md5算法加密数据 import hashlib hash = hashlib.m ...