【学习笔记】尚未用过的图论知识

本文深入探讨了多种经典的图论算法,包括斯坦纳树、最小直径生成树、最小树形图等问题的解决方法,并介绍了朱刘算法、Tarjan算法及最小环等高级主题。此外,还详细解释了BEST定理在有向欧拉图中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

斯坦纳树

不看 c 9 \sf c9 c9 的博客我都不知道有这玩意儿。属实是菜到某种境界了。

目标是,在非负边权的无向图中,选出边权和最小的连通子图,使得 k k k 个给定点在图中。显然只会选出树,树则有根。于是可以 d p \tt dp dp,记 f ( x , S ) f(x,S) f(x,S) x x x 为根的树去连通 S S S 内的关键点的最小代价。

根只有一个儿子则 f ( x , S ) ← f ( y , S ) + w ( x , y ) f(x,S)\gets f(y,S)+w(x,y) f(x,S)f(y,S)+w(x,y),有多个儿子则 f ( x , S ) ← f ( x , T ) + f ( x ,    S ∖ T )    ( T ≠ ∅ ,    T ⫋ S ) f(x,S)\gets f(x,T)+f(x,\;S\setminus T)\;(T\ne\varnothing,\;T\subsetneqq S) f(x,S)f(x,T)+f(x,ST)(T=,TS)

转移顺序,显然可以按照 ∣ S ∣ |S| S 升序。或者按照 S S S 升序,二进制值意义下。然后做第二类转移是容易的,子集枚举嘛。

第一类转移就是最短路转移,可以直接 dijkstra \texttt{dijkstra} dijkstra 等。

卡常术:应让 S S S 为数组的第一个维度,这样最短路时的内存访问很连续。同时,第二类转移也该先枚举 T T T 再枚举 i i i

最小直径生成树

枚举直径的中点,则答案是它到所有点的最远距离乘 2 2 2 。如果这不是中点,则该值偏大。

故只需找到图的中点,即最小化它到所有点的最远距离。

求出全源最短路,然后在每条边上找最优点。是个 O ( n ) \mathcal O(n) O(n) 段分段函数,每段的 min ⁡ \min min 易求。复杂度 O ( n m ) \mathcal O(nm) O(nm)

最小树形图

目标是,在带权有向图上,找出边权和最小的子图满足 r r r 到每个点都存在唯一路径(即树形图)。边权是否非负不重要,因为给所有边加上大正数即可。

因为它比较像最小生成树,所以可以贪心。有点不自然?但是逻辑是相对严谨的。这被称作朱刘算法。

树形图等价于给除了 r r r 的每个点选择入边,使得图中无环。因此,给 r r r 以外的点选择最小权入边,如果这可以构成树形图,那肯定是最优解。

否则(存在最优解使得)该环上必有恰好一条边不选。因为一条边不选,说明无法调整,说明两侧的点有与这条边相反的可达关系;若环上有至少两条边不选,就能推出环形的可达关系,矛盾。

因此该环可以缩为单点,外部向内的连边变为要替换原定入边,即减去原定入边的边权。这个新的单点也只选择一个入边,即替换一条边,符合预期。

每轮缩点至少能缩掉一个点(并不是所有点都在环中,可能只有两个点成环,其余点构成树形图),总复杂度 O ( n m ) \mathcal O(nm) O(nm),实际运行应该跑不满。

还有个 tarjan \textsf{tarjan} tarjan 算法。让所有点向 r r r 的连边,边权为 + ∞ +\infty +,不难验证这个流程是正确的:维护一个栈,初始时其中有任意点 a a a,每次取出栈顶与其最小入边,选择该入边。若已选择的入边构成环,显然是栈顶的若干点,缩点(新点仍放于栈顶),继续该流程直到整张图只剩一个点。

用并查集处理缩点,用可并堆(带标记)维护每个点的入边即可。复杂度 O ( m log ⁡ m ) \mathcal O(m\log m) O(mlogm)

Comment. 奶奶滴,为什么我算出来的复杂度和 OI-wiki \text{OI-wiki} OI-wiki 里写的不一样 😢

最小环

如果图有向,等价于从自己走到自己的最短路。用 Bellman-ford \text{Bellman-ford} Bellman-ford 可以做到 O ( a n s ⋅ n 2 ) \mathcal O(ans\cdot n^2) O(ansn2),显然 a n s ans ans 不超过 n n n

如果图无向,则可以枚举一条边并删去之,再做最短路做到 O ( m 2 log ⁡ m ) \mathcal O(m^2\log m) O(m2logm)

稠密图里更好的做法是,枚举环上编号最大的点,在 Floyed \texttt{Floyed} Floyed 过程中直接更新。复杂度 O ( n 3 ) \mathcal O(n^3) O(n3)

BEST \text{BEST} BEST 定理

有向欧拉图 G G G 的欧拉回路数量是
T ∏ v ∈ V ( deg ⁡ ( v ) − 1 ) ! T\prod_{v\in V}(\deg(v)-1)! TvV(deg(v)1)!

其中 T T T 是任意节点为根的根向树(或叶向树)的数量, deg ⁡ ( v ) \deg(v) deg(v) v v v 点的出度(或入度)。

其实就是 T T T 选择了每个节点最后一次离开的边,然后之前的离去都可以 ( deg ⁡ ( v ) − 1 ) ! (\deg(v)-1)! (deg(v)1)! 任选。根节点(回路起点)其实有 deg ⁡ ( v ) ! \deg(v)! deg(v)! 个选择,但是每条回路会被统计 deg ⁡ ( v ) \deg(v) deg(v) 次(根节点在其一截断)恰好要除以它。

感觉发现它的人还是比较有洞见力的。首先每个节点的最后一次离开不能成环,否则永远触发不了。

而不成环的时候,考虑每个点的最后一次离开:此时它的入度应该被用光,故它在根向树中的子节点走过了最后一条边。以此类推,可知它在根向树中的整棵子树都走过了最后一条边。

因此,如果内向树边不存在,则点无需再走。这说明所有仍然需要经过的点构成连通图,故而有欧拉路径,故总可以走出欧拉回路。非常奇妙。

k k k 短路

最后的提交记录停留在 2021/9/18 \texttt{2021/9/18} 2021/9/18,只有 44 44 44 分。史前巨坑了!

k k k 个最值,经常是 “将所有方案建立堆,从根节点开始 b f s \tt bfs bfs 查找” 的方法。

最小就是真实最短路。次小,则是选择一条非最短路上的边,然后强迫自己走过这条边。

完全意义上地说明它:对于非最短路边 ⟨ a , b ⟩ \langle a,b\rangle a,b,它给最短路带来增量 w + d i s ( b ) − d i s ( a ) w+dis(b)-dis(a) w+dis(b)dis(a) 。这样的边沿着最短路顺序进行选择。

因此,接下来可以怎样调整,就是问所有可用的非最短路边。这样就把所有方案的堆建了出来。

可用的非最短路边太多(堆中的子节点太多),因此也要建立堆(平衡树当然也可以,但没必要)。由于可用的非最短路边就是当前点的最短路上的非最短路邻边,因此用可持久化堆维护。

那么所有可用的后继状态就是:当前值是多少,能在某个点为根的堆里去选元素(为了模拟出 p o p \tt pop pop 的效果)。时间复杂度 O ( ( n + m ) log ⁡ m + k log ⁡ k ) \mathcal O((n+m)\log m+k\log k) O((n+m)logm+klogk),空间复杂度 O ( m log ⁡ m + k ) \mathcal O(m\log m+k) O(mlogm+k)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值