图论刷题日记
写在前面
关于图论,大概包括这些
图的存储
DFS(图论)
BFS(图论)
树上问题
矩阵树定理
有向无环图
拓扑排序
最小生成树
斯坦纳树
最小树形图
最小直径生成树
最短路
拆点
差分约束
k 短路
同余最短路
连通性相关
2-SAT
欧拉图
哈密顿图
二分图
最小环
平面图
图的着色
网络流
Prufer 序列
LGV 引理
弦图
次小生成树(非严格,kruscal板)
通过这个图我们可以看到的是,我们需要在原有的最小生成树的基础上,在另外找一个边,使其变成次小生成树
首先我们可以跑一边 \(kruscal\) 将最小生成树建立出来,并设置一个 \(big[i][j]\) 表示 \(i\) 到 \(j\) 的路径上的最大权值,我们可以通过没有在最小生成树上的边来与最小生成树上的边进行比较,可以得出公式
其中 \(sml_{tree}\) 为最小生成树树的总权值,\(w\) 为当前不在最小生成树上的边
本笔记主要是记录自己的刷题的历程以及中心思路,对知识点的讲解会不时更新
当图中存在唯一的最小生成树时改算法适用,否则求出来的值不变,仅仅为另外一个次小生成树
\(spfa\)的\(dfs\)优化+判负环
\(spfa\) 的 \(dfs\) 优化通过以一个点为开头,通过松弛操作不断迭代,直到找到找到一个曾经被找过的点时,即可找到一个环
\(spfa\) 的 \(dfs\) 优化可以通过二分和公式推论(找松弛条件)来达到求最值的问题,解决了查找时无法准确记录权值的问题
对于找负环,可以有两种做法,一是通过 \(dfs\) 优化来判断是否有负环,二是可以通过一个点入队的次数\(\ge n\) 来判断
相对于 \(dfs\) 优化找负环,判断入队次数更加的稳定,且不容易被刻意的样例卡掉
例题
1、黑暗城堡
思路
-
对于点的数据范围 \(n\le 10^3\),考虑用邻接矩阵进行解答,更加简单
-
该题首先给出所有的道路修建的可能性边,求解 $ m $ 条边全部建完时 \((1,i)\) 的最短路 \(D_i\),和实际情况下建好的边所形成的图中 \((1,i)\) 的最短路 \(S_i\) 相等的建设方案数,并对 \(2^{31}-1\)取摸即可
-
需要注意的是最好开 \(long long\)
-
首先在存图的时候做一个操作,因为是双向图,所有正反存这个没有问题,其次就是可能会出现重复的边的情况,那么对于完全建好的图的最短路,重复的边中不是最小边的所有边没有贡献,所有建边的时候对边的权值取一个 \(min\) 即可
-
其次通过邻接矩阵版的\(dj\)求出从所有的 \((1,i)\)的最短路
-
最后根据乘法原理判断就可以了,乘法技术原理可以参考组合数学第一节OVO。
代码
2、北极通讯网络
思路
-
思路很简单,首先枚举一遍所有的距离,并用最小生成树的方法进行升序排列,从最小的距离开始一一枚举。
-
因为无线电在两个村庄中只需要建造一个,所以所设置的 \(cnt\) 为可能一共可以设置的数量
-
按照村庄之间可以间接或者直接的连接可以得出来,用并查集来做即可
-
每次发现没有可以直接或者间接的连接的村庄就记录一下距离,直到记录到 \(cnt=\)可以设置的卫星的数量时停止,此时记录的就是最小的答案值
代码
3、新的开始
思路
-
唯一的一个坑点就是误以为电站只能建造一个=_=
-
其实可以将 \(0\) 点看做电站的来源点,将所有点与 \(0\) 点连接,权值为在该点建造电站的费用
-
其他的电网用边连接起来
-
跑最小生成树即可
代码
4、构造完全图
思路
-
通过手模样例可以发现,从最小的权值向最大的权值连边的限制就会越来越小
-
所以就跑一边最小生成树,从小向大的依次累加即可
-
每一次求边的时候只需要 \(+\) 当前的权值 \(+1\)
代码
5、秘密的牛奶运输
见非严格次小生成树
6、最小生成树计数
思路
-
首先有一个万古不变的真理:一个图中的最小生成树,不管怎么改变边,一个的权值的边的数量在最小生成树中是固定不变的
-
那么根据这个来开始找就行了
-
首先建立一棵最小生成树,并按照边权升序排列,随后就把每一种边权的左右端点都找出来,\(dfs\)一遍找一找有多少满足的边即可,用乘法原理计算答案
代码
7、\(Word Rings\)
思路
-
这个题目可以通过一个随随便便的哈希把每个字符串的前两个字母和后两个字母转换数字来连边,每一个字符串的开头两个字母和结尾两个字母连一条\(w=len_s\)的边
-
因为是让我们进行找环,并且要找出平均长度最大的环,那么可以考虑二分一下\(ans\)
那么二分成立的条件即可为:
代码
8、双调路径
思路
-
\(dp\) 竟在图论中???
-
首先可以设置状态
设 \(dis[i][j]\) 为一共经过 \(j\) 的距离到达 \(i\) 点所用的最小时间
- 求得转移方程(假设当前节点\(u\),走到的距离为\(w\),连接点\(v\)的长度为 \(val\),走这条路所需时间为 \(time\) )
- 最后以距离为第一关键字, 时间为第二关键字来找个数,注意最短路径是指路程或者时间更小的路径