2024.8.24

news2024/9/20 8:52:05

130124202408241009


DATE #:20240824

ITEM #:DOC

WEEK #:SATURDAY

DAIL #:捌月廿壹

TAGS
< BGM = "风屿--闫东炜" >
< theme = oi-graph theory  >
< [NULL] >
< [空] > 
< [空] >
``` 与风为名,屿之齐鸣。——风屿 ```

## LGV引理

LGV 引理,全称 Lindstrom-Gessel-Viennot lemma

用于求解DAG上的不相交路径数,也就是生成树数量

内容:

  • 经典

给出一个无向无权图,设 A 为邻接矩阵, D 为度数矩阵(D[i][i]=节点 i 的度数,其他的无值)。

则基尔霍夫(Kirchhoff)矩阵即为 : K=D−A

然后令 K′ 为 K 去掉第k行与第k列(k任意)的结果(n−1阶主子式),

det⁡(K′) 即为该图的生成树个数。

  • 加权扩展

容易理解 : 带重边的情况,上面的经典矩阵树定理也是能够处理的。

根据乘法原理,对于某种生成树的形态,其贡献为每条边重的次数的乘积

如果把重边次数理解成权值的话,那么矩阵树定理求的就是 : 所有生成树边权乘积的总和。

(这里注意度数矩阵变成了相邻边的权值和)

  • 有向扩展

前面都是无向图,神奇的是有向图的情况也是可以做的。

(邻接矩阵 A 的意义同有向图邻接矩阵)

那么现在的矩阵 D 就要变一下了。

D [ i ] [ i ] = ∑ j = 1 n A [ j ] [ i ] D[i][i]=\sum_{j=1}^nA[j][i] D[i][i]=j=1nA[j][i] ,即到该点的边权总和(入)

此时求的就是外向树 (从根向外)

D [ i ] [ i ] = ∑ j = 1 n A [ j ] [ i ] D[i][i]=\sum_{j=1}^nA[j][i] D[i][i]=j=1nA[j][i] ,即从从该点出发的边权总和(出)

此时求的就是内向树 (从外向根)

(如果考场上不小心忘掉了,可以手玩小样例)

(同样可以加权!)

此外,既然是有向的,那么就需要指定根

前面提过要任意去掉第 k 行与第 k 列,是因为无向图所以不用在意谁为根。

在有向树的时候需要理解为指定根,结论是 : 去掉哪一行就是那一个元素为根。

(来自command_block)矩阵树定理(+行列式) - 洛谷专栏 (luogu.com.cn)

证明


P6178 [模板]Matrix-Tree 定理

【模板】Matrix-Tree 定理

题目描述

给定一张 n n n 个结点 m m m 条边的带权图(可能为无向图,可能为有向图)。

定义其一个生成树 T T T 的权值为 T T T 中所有边权的乘积。

求其所有不同生成树的权值之和,对 1 0 9 + 7 10^9+7 109+7 取模。


注意:

  1. 本题中,有向图的生成树指的是 1 1 1 为根的外向树

  2. 两棵生成树 T 1 , T 2 T_1,T_2 T1,T2 不同,当且仅当存在存在一条边 e e e,满足 e ∈ T 1 ,    e ∉ T 2 e\in T_1,\ \ e\notin T_2 eT1,  e/T2

输入格式

第一行:三个整数 n , m , t n,m,t n,m,t,分别表示图的结点数量,边的数量和图的类型( t = 0 t=0 t=0 时为无向图, t = 1 t=1 t=1 时为有向图)。

接下来 m m m 行:每行三个整数 u , v , w u,v,w u,v,w

如果 t = 0 t=0 t=0,表示 u , v u,v u,v 之间有一条权值为 w w w 的无向边;

如果 t = 1 t=1 t=1,表示从 u u u v v v 有一条权值为 w w w 的有向边。

输出格式

第一行:一个整数 a n s ans ans,表示给定的图的生成树权值和对 1 0 9 + 7 10^9+7 109+7 取模的结果。

样例 #1

样例输入 #1

5 8 0
2 3 1
1 2 3
4 5 1
4 2 2
3 5 2
3 4 3
3 4 1
3 3 5

样例输出 #1

144

样例 #2

样例输入 #2

5 9 1
1 2 3
3 2 1
1 3 1
2 4 2
3 5 1
4 3 4
3 5 1
5 4 1
4 4 6

样例输出 #2

72

提示

【样例 1 1 1 解释】

样例 1 1 1 中的无向图如左图所示:

右图为其一个权值为 3 × 1 × 2 × 3 = 18 3\times 1\times 2\times 3=18 3×1×2×3=18 的生成树的例子。


【样例 2 2 2 解释】

样例 2 2 2 中的有向图如左图所示:

右图为其一个权值为 1 × 1 × 1 × 2 = 2 1\times 1\times 1\times 2=2 1×1×1×2=2 的生成树(以 1 1 1 为根的外向树)的例子。


【数据范围】

对于 100 % 100\% 100% 的数据: 1 ≤ n ≤ 300 ,    1 ≤ m ≤ 1 0 5 ,    t ∈ { 0 , 1 } ,    1 ≤ u , v ≤ n ,    1 ≤ w ≤ 1 0 9 1\leq n\leq 300,\ \ 1\leq m\leq 10^5,\ \ t\in \{0,1\},\ \ 1\leq u,v\leq n,\ \ 1\leq w\leq 10^9 1n300,  1m105,  t{0,1},  1u,vn,  1w109

对于测试点 1 , 2 , 3 , 4 , 5 , 6 1,2,3,4,5,6 1,2,3,4,5,6 t = 0 t=0 t=0;对于测试点 7 , 8 , 9 , 10 , 11 7,8,9,10,11 7,8,9,10,11 t = 1 t=1 t=1

图中 可能 存在重边和自环,重边算作多条边。

//2024.8.24
//by white_ice
//【模板】Matrix-Tree 定理 | P6178
//model
#include<bits/stdc++.h>
//ss#include"need.cpp"
using namespace std;
#define itn long long 
#define int long long 
constexpr int oo = 302;
constexpr itn mod = 1000000007;
itn n,m,t;
itn mp[oo][oo],out = 1;
__inline void lgv(){
    itn flag = 1;
    for (itn i=1;i<=n;i++){
        for (itn j=i+1;j<=n;j++){
            while (mp[j][i]){
                itn p = mp[i][i]/mp[j][i];
                for (itn k=i;k<=n;k++){
                    mp[i][k] = (mp[i][k]-p*mp[j][k]+mod)%mod;
                    swap(mp[i][k],mp[j][k]);
                }
                flag *= -1;
            }
        }
        (out *= mp[i][i])%=mod;
    }
    out = (out*flag+mod)%mod;
}
main(void){
    //fre();
    cin.tie(0)->sync_with_stdio(0);
    cin >> n >> m >> t;
    for (itn a,b,c,i=1;i<=m;i++){
        cin >> a >> b >> c;  a--,b--;
        if(!t){
            mp[a][a] = (mp[a][a]+c)%mod;
            mp[b][b] = (mp[b][b]+c)%mod;
            mp[a][b] = (mp[a][b]-c+mod)%mod;
            mp[b][a] = (mp[b][a]-c+mod)%mod;
        }
        else {
            mp[b][b] = (mp[b][b]+c)%mod;
            mp[b][a] = (mp[b][a]-c+mod)%mod;
        }
    }
    n--;lgv();
    cout << out << '\n';
    exit(0);
}

P4336 [SHOI2016] 黑暗前的幻想乡

[SHOI2016] 黑暗前的幻想乡

题目背景

四年一度的幻想乡大选开始了,最近幻想乡最大的问题是很多来历不明的妖怪涌入了幻想乡,扰乱了幻想乡昔日的秩序。但是幻想乡的建制派妖怪(人类)博丽灵梦和八云紫等人整日高谈所有妖怪平等,幻想乡多元化等等,对于幻想乡目前面临的种种大问题却给不出合理的解决方案。

风见幽香是幻想乡里少有的意识到了问题严重性的大妖怪。她这次勇敢地站了出来参加幻想乡大选,提出包括在幻想乡边境建墙(并让人类出钱),大力开展基础设施建设挽回失业率等一系列方案,成为了大选年出人意料的黑马并顺利地当上了幻想乡的大统领。

题目描述

幽香上台以后,第一项措施就是要修建幻想乡的公路。幻想乡一共有 n n n 个城市,之前原来没有任何路。幽香向选民承诺要减税,所以她打算只修 n − 1 n-1 n1 条公路将这些城市连接起来。但是幻想乡有正好 n − 1 n-1 n1 个建筑公司,每个建筑公司都想在修路的过程中获得一些好处。虽然这些建筑公司在选举前没有给幽香钱,幽香还是打算和他们搞好关系,因为她还指望他们帮她建墙。所以她打算让每个建筑公司都负责一条路来修。

每个建筑公司都告诉了幽香自己有能力负责修建的路是哪些城市之间的。所以幽香打算 n − 1 n - 1 n1 条能够连接幻想乡所有城市的边,然后每条边都交给一个能够负责该边的建筑公司修建,并且每个建筑公司都恰好修建一条边。

幽香现在想要知道一共有多少种可能的方案呢?两个方案不同当且仅当它们要么修的边的集合不同,要么边的分配方式不同。

输入格式

第一行包含一个整数 n n n,表示城市个数。

2 2 2 到第 n n n 行,第 ( i + 1 ) (i + 1) (i+1) 行表示 第 i i i 个建筑公司可以修建的路的列表:以一个非负整数 m i m_i mi 开头,表示其可以修建条路的条数;接下来有 m i m_i mi 对整数 u , v u, v u,v,每对数表示一条边的两个端点。其中不会出现重复的边,也不会出现自环。

输出格式

输出一行一个整数,表示所有可能的方案数对 1 0 9 + 7 10^9+7 109+7 取模的结果。

样例 #1

样例输入 #1

4
2 3 2 4 2
5 2 1 3 1 3 2 4 1 4 3
4 2 1 3 2 4 1 4 2

样例输出 #1

17

提示

数据规模与约定
  • 对于 20 % 20\% 20% 的测试点, n ≤ 5 n \le 5 n5
  • 对于 50 % 50\% 50% 的测试点, n ≤ 8 n \le 8 n8
  • 对于 60 % 60\% 60% 的测试点, n ≤ 10 n \le 10 n10
  • 对于 100 % 100\% 100% 的测试点, 2 ≤ n ≤ 17 2 \leq n \le 17 2n17 0 ≤ m i ≤ n ( n − 1 ) 2 0 \leq m_i \leq \frac{n(n - 1)}{2} 0mi2n(n1) 1 ≤ u , v ≤ n 1 \leq u, v \leq n 1u,vn
//2024.8.24
//by white_ice
//[SHOI2016] 黑暗前的幻想乡 | P4336
//LGV,容斥
#include<bits/stdc++.h>
//#include"need.cpp"
using namespace std;
#define itn long long 
#define int long long 
constexpr int oo = 20;
constexpr int mod = 1e9+7;
itn n,m;
itn mp[oo][oo];
vector<pair<int,int>> q[oo];
__inline int det(){
	int out=1;
	for(int i=1;i<=n;++i){
		int p=-1;
		for(int j=i;j<=n;++j)
			if(mp[i][j]){p=j;break;}
		if(!~p) return 0;
		if(p!=i){swap(i,p);out*=-1;}
		for(int j=i+1;j<=n;++j){
			while(mp[j][i]){
				int tmp=mp[j][i]/mp[i][i];
				for(int k=i;k<=n;++k){
					mp[j][k]-=1ll*tmp*mp[i][k]%mod;
					mp[j][k]=(mp[j][k]%mod+mod)%mod;
				} 
				if(!mp[j][i]){break;}
				swap(mp[i],mp[j]);
				out*=-1;
			}
		}
		out=out*mp[i][i]%mod;
	}
	return out;
}
main(void){
    //fre();
    cin.tie(0)->sync_with_stdio(0);
    cin >> n;n--;
    for (itn x,y,i=1;i<=n;i++){
        cin >> m;
        while (m--){
            cin >> x >> y;
            q[i].push_back(make_pair(x,y));
        }
    }
    itn out = 0;
    for(int i=1;i<(1<<n);++i){
		memset(mp,0,sizeof(mp));
		int cnt=0;
		for(int j=1;j<=n;++j){
			if(!(i&(1<<(j-1)))){
				continue;
			}
			++cnt;
			for(int k=0;k<q[j].size();++k){
				int x=q[j][k].first,y=q[j][k].second;
				++mp[x][y],++mp[y][x];
                --mp[x][x],--mp[y][y];
			}
		}
		out=(out+((cnt&1)?-1:1)*det())%mod;
	}
    out = (out+mod)%mod;
    cout << out << flush;
    exit(0); 
}

考虑当没有每个公司只能修一条路的限制,那么就直接计数,LGV求解生成树即可

观察数据范围,很难不发现,n很小,可以状压枚举每种选k个公司给方案

每次将枚举的公司所能修的路加入矩阵并求解生成树

之后考虑容斥解题,记 f i f_i fi k = i k=i k=i时可能的方案数

那么答案就是
∑ f 1 − ∑ f 2 + ∑ f 3 ⋯ ± ∑ f n \sum f_1-\sum f_2 +\sum f_3 \dots \pm \sum f_n f1f2+f3±fn
当然,符号正负取决于选数个数的奇偶性

如此枚举即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2072726.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MFC工控项目实例之六CFile添加菜单栏

本程序基于前期我的博客文章《MFC工控项目实例之五CFile类读写系统参数》 添加两个对话框如下 具体添加菜单栏参考我的博客文章MFC_ CFile类实现下拉菜单读写实例&#xff08;源码下载&#xff09; 这里给出相关代码 在 SEAL_PRESSURE.h文件中添加 #include <afxtempl.…

github源码指引:共享内存、数据结构与算法

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码目录&#xff1a;shmfc 相…

一键拼图神器CollageIt,让你的照片秒变艺术大作!

前言 嘿&#xff0c;你是否曾对着满屏的照片发愁&#xff0c;想要快速整理成精美的作品集&#xff0c;却又被繁琐的排版搞得头昏脑涨&#xff1f;如果有一款神器&#xff0c;能让你一键搞定这些烦恼&#xff0c;轻松提升办公效率&#xff0c;是不是觉得升职加薪的曙光就在眼前…

Python 进度条tqdm应用记录

tqdm 简介 tqdm 是一个非常流行的 Python 库&#xff0c;用于快速添加进度条到循环中。它可以方便地集成到脚本中&#xff0c;并且支持多种类型的迭代器。 安装 首先确保你安装了 tqdm。如果还没有安装&#xff0c;可以通过 pip 安装它&#xff08;如果要在 jupyter noteboo…

游戏开发设计模式之单例模式

单例模式&#xff08;Singleton Pattern&#xff09;是一种常见的设计模式&#xff0c;其主要目的是确保一个类在整个程序的生命周期中只有一个实例&#xff0c;并提供一个全局访问点来获取这个实例。在游戏开发中&#xff0c;单例模式具有广泛的应用和重要的作用。 单例模式的…

如何评估Redis的性能

如果系统中出现了大 key、热 key 等&#xff0c;往往会导致 Redis 变慢&#xff0c;但是这个慢该如何界定&#xff1f;多久算慢&#xff1f;1秒还是3秒&#xff1f; 这个肯定是没有标准答案&#xff0c;因为这个和你的硬件设备有关。 硬件差一些&#xff0c;平时响应时间都是…

OSPF路由原理详解与关键点

目录 一. OSPF简介: 二. OSPF原理描述: 三. OSPF的核心内容: 四. OSPF的邻居关系和邻接 五. LSA在各区域中传播的支持情况 一. OSPF简介: 开放式最短路径优先OSPF&#xff08;Open Shortest Path First&#xff09;是IETF组织开发的一个基于链路状态的内部网关协议&…

打造编程学习的知识宝库:高效笔记与整理技巧

在编程的海洋中&#xff0c;知识的深度和广度都是难以估量的。要想在这片海洋中航行而不迷失方向&#xff0c;一个高效的笔记系统是不可或缺的。本文将探讨如何建立一个既能快速记录又易于回顾的笔记系统&#xff0c;以及如何在繁忙的学习中保持笔记的条理性。 目录 一、确定笔…

数三角形(二)》-筛除法斜线结论

算法思路&#xff1a; 1、一个直观的思路是筛除法&#xff0c;即&#xff1a;答案总数-三点共线的种数 总数易求得&#xff0c;为组合数C((n1)*(m1),3)&#xff0c;考虑到n、m数值范围&#xff0c;考虑用long long。 2、三点共线的情况有&#xff1a; &#xff08;1&#xff09…

Linux驱动学习之按键读取

按键读取我们需要实现read函数&#xff0c; read 函数的 第二个参数被__user 修饰&#xff0c;原则上在内核层我们不能直接访问&#xff0c;需要调用 copy_to_user()这个函数&#xff0c;从内核获取数据到上层。 copy_to_user(void __user volatile * to, const void * from,…

C语言笔试题(指针、数组、整数在内存中的存储、结构体......)

文章目录 1.选择题2.代码题2.1 模拟实现strncat2.2 模拟实现strncpy2.3 编写判断大小端程序2.4 模拟实现atoi2.5 BC38 变种水仙花数2.6 BC98 序列中删除指定数字 今天我们一起来看一些题目 1.选择题 解析如下&#xff1a; 正确选项&#xff1a;B A.参数错误&#xff1b;D.返回…

什么是Redis集群的脑裂问题?

目录 一、脑裂的发生 二、脑裂的危害 三、如何避免脑裂&#xff1f; 四、能彻底解决脑裂吗&#xff1f; 所谓脑裂&#xff0c;就像他的名字一样&#xff0c;大脑裂开了&#xff0c;一般来说就是指一个分布式系统中有两个子集&#xff0c;然后每个子集都有一个自己的大脑(Le…

【Excal】And函数

奖金评定说明 业绩低于6000&#xff0c;奖金为100 业绩大于等于6000且小于10000&#xff0c;奖金为200 业绩大于等于10000&#xff0c;奖金为500 然后按回车健 下拉填充

BurpSuite2024.7.3专业版

前言 Burp Suite是一个无需安装软件&#xff0c;下载完成后&#xff0c;直接从命令行启用即可。开箱即可使用支持LInux/Windows/Mac 01更新介绍 2024.7.13版本界面大改动此版本引入了重大的性能升级、对拦截功能的重大增强&#xff0c;以及在审计项目表中新增了扫描插入点列。…

【Nature】在科研中应用ChatGPT:如何与数据对话

随着人工智能技术的迅猛发展&#xff0c;大型语言模型&#xff08;LLMs&#xff09;正逐渐成为科研领域的一种创新工具。这些模型通过自然语言处理技术&#xff0c;使得研究人员能够以直观的方式与数据进行交互&#xff0c;从而简化了数据分析和解释的过程。在《自然》杂志2024…

103.二叉树的锯齿形层序遍历

1.题目描述 给你二叉树的根节点 root &#xff0c;返回其节点值的 锯齿形层序遍历 。&#xff08;即先从左往右&#xff0c;再从右往左进行下一层遍历&#xff0c;以此类推&#xff0c;层与层之间交替进行&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,nul…

Unity-可分组折叠的Editor

Unity-可分组折叠的Editor &#x1f957;功能介绍&#x1f36d;用法 &#x1f957;功能介绍 在序列化的字段上标记特性:[FoldoutGroup(“xxx”)]&#xff0c;inspector上就会被分组折叠显示。 &#xff08;没有被指定的字段自动放到Default组中&#xff09; 传送门&#x1f30…

如何用Java SpringBoot和Vue搭建高效的OA办公管理系统?

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

深度学习--复制机制:CopyNet 模型在序列到序列模型中的应用以及代码实现

CopyNet 是一种特别设计的序列到序列&#xff08;Seq2Seq&#xff09;模型&#xff0c;旨在更好地处理那些在输出序列中需要直接复制输入序列中的部分或全部内容的任务。它在机器翻译、摘要生成、文本复述等任务中有广泛的应用&#xff0c;尤其是在输入和输出有显著重叠的场景。…

Spring--三级缓存机制

一、什么是三级缓存 就是在Bean生成流程中保存Bean对象三种形态的三个Map集合&#xff0c;如下&#xff1a; // 一级缓存Map 存放完整的Bean&#xff08;流程跑完的&#xff09; private final Map<String, Object> singletonObjects new ConcurrentHashMap(256);// 二…