生成树的计数 Matrix-Tree(矩阵树)定理
信息学竞赛中,有关生成树的最优化问题如最小生成树等是我们经常遇到的,而对生成树的计数及其相关问题则少有涉及。事实上,生成树的计数是十分有意义的,在许多方面都有着广泛的应用。本文从一道信息学竞赛中出现的例题谈起,首先介绍了一种指数级的动态规划算法,然后介绍了行列式的基本概念、性质,并在此基础上引入Matrix-Tree定理,同时通过与一道数学问题的对比,揭示了该定理所包含的数学思想。最后通过几道例题介绍了生成树的计数在信息学竞赛中的应用,并进行总结。
生成树的计数 Matrix-Tree定理
问题的提出
[例一]高速公路(SPOJ 104 Highways)
一个有n座城市的组成国家,城市1至n编号,其中一些城市之间可以修建高速公路。现在,需要有选择的修建一些高速公路,从而组成一个交通网络。你的任务是计算有多少种方案,使得任意两座城市之间恰好只有一条路径?
数据规模:1≤n≤12。
[分析]
我们可以将问题转化到成图论模型。因为任意两点之间恰好只有一条路径,所以我们知道最后得到的是原图的一颗生成树。因此,我们的问题就变成了,给定一个无向图G,求它生成树的个数t(G)。这应该怎么做呢?
经过分析,我们可以得到一个时间复杂度为O(3n*n2)的动态规划算法,因为原题的规模较小,可以满足要求。但是,当n再大一些就不行了,有没有更优秀的算法呢?答案是肯定的。在介绍算法之前,首先让我们来学习一些基本的预备知识。
新的方法介绍
下面我们介绍一种新的方法——Matrix-Tree定理(Kirchhoff矩阵-树定理)。Matrix-Tree定理是解决生成树计数问题最有力的武器之一。它首先于1847年被Kirchhoff证明。在介绍定理之前,我们首先明确几个概念:
1、G的度数矩阵D[G]是一个n*n的矩阵,并且满足:当i≠j时,dij=0;当i=j时,dij等于vi的度数。
2、G的邻接矩阵A[G]也是一个n*n的矩阵, 并且满足:如果vi、vj之间有边直接相连,则aij=1,否则为0。
我们定义G的Kirchhoff矩阵(也称为拉普拉斯算子)C[G]为C[G]=D[G]-A[G],则Matrix-Tree定理可以描述为:G的所有不同的生成树的个数等于其Kirchhoff矩阵C[G]任何一个n-1阶主子式的行列式的绝对值。所谓n-1阶主子式,就是对于r(1≤r≤n),将C[G]的第r行、第r列同时去掉后得到的新矩阵,用Cr[G]表示。
生成树计数
算法步骤:
1、 构建拉普拉斯矩阵
Matrix[i][j] =
degree(i) , i==j
-1,i-j有边
0,其他情况
2、 去掉第r行,第r列(r任意)
3、 计算矩阵的行列式
论文 周冬 《生成树计数应用》
#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 105;
const int maxm = 100005;
const int INF = 1e9;
int degree[maxn];
ll g[maxn][maxn];
int n, m; ll det(ll a[][maxn], int n)
{
ll ret = 1;
for(int i=1; i<n; ++i){
for(int j=i+1; j<n; ++j){
while(a[j][i]){
ll t = a[i][i]/a[j][i];
for(int k=i; k<n; ++k){
a[i][k] = (a[i][k]-a[j][k]*t);
}
for(int k=i; k<n; ++k){
swap(a[i][k], a[j][k]);
}
ret = -ret;
}
}
if(a[i][i]==0){
return 0;
}
ret = ret*a[i][i];
}
if(ret<0){
ret = -ret;
}
return ret;
} void solve()
{
int u, v;
memset(degree, 0, sizeof degree );
memset(g, 0, sizeof g );
scanf("%d%d", &n, &m);
while(m--){
scanf("%d%d", &u, &v);
u--,v--;
g[u][v] = g[v][u] = -1;
degree[u]++;
degree[v]++;
}
for(int i=0; i<n; ++i){
g[i][i] = degree[i];
}
printf("%lld\n", det(g, n));
} int main()
{
int t;
scanf("%d", &t);
while(t--){
solve();
}
return 0;
}
生成树的计数 Matrix-Tree(矩阵树)定理的更多相关文章
- 【算法】Matrix - Tree 矩阵树定理 & 题目总结
最近集中学习了一下矩阵树定理,自己其实还是没有太明白原理(证明)类的东西,但想在这里总结一下应用中的一些细节,矩阵树定理的一些引申等等. 首先,矩阵树定理用于求解一个图上的生成树个数.实现方式是:\( ...
- 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)
1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...
- 【BZOJ1016】【Luogu P4208】 [JSOI2008]最小生成树计数 最小生成树,矩阵树定理
蛮不错的一道题,遗憾就遗憾在数据范围会导致暴力轻松跑过. 最小生成树的两个性质: 不同的最小生成树,相同权值使用的边数一定相同. 不同的最小生成树,将其都去掉同一个权值的所有边,其连通性一致. 这样我 ...
- spoj104 highways 生成树计数(矩阵树定理)
https://blog.csdn.net/zhaoruixiang1111/article/details/79185927 为了学一个矩阵树定理 从行列式开始学(就当提前学线代了.. 论文生成树的 ...
- 【bzoj1002】[FJOI2007]轮状病毒 矩阵树定理+高精度
题目描述 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道.如下图所示 N轮状病 ...
- Codeforces 917D - Stranger Trees(矩阵树定理/推式子+组合意义)
Codeforces 题目传送门 & 洛谷题目传送门 刚好看到 wjz 在做这题,心想这题之前好像省选前做过,当时觉得是道挺不错的题,为啥没写题解呢?于是就过来补了,由此可见我真是个大鸽子(( ...
- @总结 - 7@ 生成树计数 —— matrix - tree 定理(矩阵树定理)与 prüfer 序列
目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 矩阵树定理主体@ @证明 part - 1@ @证明 part - 2@ @证明 part - 3@ @证明 part ...
- [spoj104][Highways] (生成树计数+矩阵树定理+高斯消元)
In some countries building highways takes a lot of time... Maybe that's because there are many possi ...
- 【bzoj2467】[中山市选2010]生成树 矩阵树定理
题目描述 有一种图形叫做五角形圈.一个五角形圈的中心有1个由n个顶点和n条边组成的圈.在中心的这个n边圈的每一条边同时也是某一个五角形的一条边,一共有n个不同的五角形.这些五角形只在五角形圈的中心的圈 ...
随机推荐
- Ubuntu 进入、退出命令行的快捷键
进入: Ctrl+Alt+F1 退出: Ctrl+Alt+F7(或者 Alt+F7) 进入命令行窗口:Ctrl+Alt+T
- 饮冰三年-人工智能-Python-10之C#与Python的对比
1:注释 C# 中 单行注释:// 多行注释:/**/ python 中 单行注释:# 多行注释:“““内容””” 2:字符串 C#中 "" 用双引号如("我是字符串&q ...
- HDU 1075 What Are You Talking About (stl之map映射)
What Are You Talking About Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/204800 K ...
- jqurey实现点赞特效
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Java数据类型Stack栈、Queue队列、数组队列和循环队列的比较
判断括号是否匹配:调用java本身 import java.util.Stack; public class Solution { public boolean isValid(String s){ ...
- gradle repo conf - maven-central.storage-download.googleapis.com
repositories { google() jcenter() maven { // The google mirror is less flaky than mavenCentral() url ...
- 一脸懵逼学习Hadoop分布式集群HA模式部署(七台机器跑集群)
1)集群规划:主机名 IP 安装的软件 运行的进程master 192.168.199.130 jdk.hadoop ...
- 【AtCoder】ARC073
ARC 073 C - Sentou 直接线段覆盖即可 #include <bits/stdc++.h> #define fi first #define se second #defin ...
- lvs介绍
1Linux集群及系统扩展的方式概述 集群是有多台服务器组织在一起,一起工作,因为单台服务器的并发响应能力是有限的,响应处理能力也是有限的所有有了集群的出现 在系统扩展有2种方法: 1 向上扩展:是指 ...
- selenium课程笔记
selenium课程笔记第一天(2017-7-1) 一.配置火狐浏览器 运行:firefox.exe -p -no -remote selenium课程笔记第二天 用Eclipse+java+sele ...