图论整理
- 图的遍历 太菜了完全不会啊
点的染色
EASY 可以发现任意找一个点染成一种颜色就行了。至于方案数可以发现在确定一个点的染色方案下只能有一种染色情况。于是答案为2的连通分量的个数次方。
边的染色
离谱的题目。
- 欧拉路和欧拉回路
欧拉路需要图联通并有0或2个度数为奇数的点,
欧拉回路则需要图联通并没有度数为奇数的点。
输出路径则需要把遍历到的所有点加入栈中最后倒序输出(避免中间有些地方没有走到)
(1)骑马修栅栏(USACO3.3)
注意到就是裸的欧拉路,但是要输出字典序最小。找路的时候优先找最小的就行(先搜索就最后回溯,就先输出出来),找的时候先从小的点找就行了。
(2)几笔画
考虑欧拉路也可以把奇点连虚边,剩下两个奇点的时候跑欧拉路,再进行断环来找到答案。
实现的时候比较麻烦,需要考虑图不连通情况。
- 最短路算法
(1)Dijkstra
就那样那样。。注意堆优化仅用于稀疏图中。
New question 正确性证明
我们考虑证明被更新过的点均为已经求得最短路长度的点。
使用归纳法,只有起点被更新的时候显然是成立的。
我们需要证明在进行一次更新的时候,已经被更新的点的最短路不会再被更新。
(2)方格最短路
\(假设当前选出的节点是 v,设 dist[v] = x。类似于上一小节的方法,我们可以证明剩下 还没有选出过的点的 dist 只有 x、x + 1 和 x + 2 三种情况;而且用 dist[v] 去更新其他点,也只会出现这三种情况。 我们可以准备 3 个桶 A、B、C,分别存储 dist 为 x、x + 1 和 x + 2 的点。我们从 A 中随便取出一个点,都能保证它的 dist 是当前最小的。当 A 取空了,接下 来最小的 dist 就从 x 变成了 x + 1,对应 B 桶的元素。此时原先的 B 桶就能看作新的 A 桶,原先的 C 桶可以看作新的 B 桶。 在我们用不同的点更新 u 的过程中,dist[u] 最多减少 3 次,分别是:+∞ → x + 2、 x + 2 → x + 1 和 x + 1 → x。但并不一定每个点都会经历 3 次减少,有可能一次性就减少 到了 x + 1,也有可能之后没有再减少到 x。 在减少的时候,我们还要考虑维护桶——有可能我们会需要从 C 桶中取出一个元素 放入 A 桶。这件事和堆的懒删除一样,我们不用真的从 C 中取出,而只用在真的取出 u 的时候判断 dist[u] 是否等于 x。如果等于 x,说明未曾删除;如果小于 x,说明之前删除 过;当然不可能大于 x,否则就不会在这个桶里面了。 设边权的最大取值为 h,这个算法的复杂度为 Θ(|V|h + |E|)。 下面是一个实现,其中位运算是为了方便滚动使用数组,并且节省取模操作;实现中将 需要的桶数从 3 扩充为了 4,以后设计到除法的问题时也可以用这种“略微浪费”空间, 但“省”时间的做法。\)
(3)边权离散(0/1等小边权)最短路广搜即可。
(4)Floyd
注意其算法本质是动态规划压掉一维。
(5)SPFA 永远滴神,负权图专用。
考虑最短路其实是一种解决没有拓扑序的算法。相当于通过多次松弛来使状态收敛(最优)
- 拓扑序和最短路及DP
>>拓扑排序后dp
在拓扑序下可以进行dp
(1)赚差价
考虑设f[i][0/1]为走到哪个点有没有圣物时的最大收益,没有圣物可以从上个点有/无圣物转移,有圣物也可以从上一个点有无圣物转移,或者从当前点无圣物转移。
(2)乘积最小的路径
直接Dijkstra更新。为了保证相对误差,用long long记录前20位即可。
相对误差:abs(答案-你的答案)/答案
绝对误差:abs(答案-你的答案).
>>最短路上的dp
(1)最短路计数。
所有点的最短路相当于一个有向无环图,在上面就可以dp了。
也就是边更新最短路边计算一下方案数就可以啦。
- 分层图上的最短路
(1)大中锋的游乐场
考虑某个点u分出20个点然后跑最短路就行了。比如当前吃了2个汉堡然后下一个点是3给汉堡那可以从2个汉堡的u到5个汉堡的v。最后跑一边最短路就行了。
(2)迷路
同理。
>>部分拓扑序
不 会 且 不 学 了
- Tarjan算法
(1)缩点/强连通分量
对于缩点不影响答案正确性的情况下完全可以缩点,可以把图变为一个有向无环图(也可能无向),然后可以在新图上解决一些问题且可以进行动态规划了。
Grass Cownoisseur G 考虑首先缩点,然后把新图分为两层即可。(像动态规划的分层图)
受欢迎的牛 先缩点(找到强连通分量)出度为0的即为受欢迎的牛,若有多个即无解
(2)割点/割边
割点:某个点的儿子不能到达比他更早的点那么这个点就是割点,或者树根有两个及以上儿子则也是割点。删掉割点后原图不连通
割边:同理,则为割边。
>>BLO-Blockade 对于一个普通的点,删掉后显然之后自己到别人和别人到自己的访问不会发生,即2(n-1)次访问。对于一个割点,那么分出的任意两个连通块之间都不会互相访问。记录一下割点割下来的连通块然后计算即可。
>>矿场搭建 先计算出所有的割点然后记录每个连通块中的割点的个数。如果割点是一个那么说明这个连通块必须要建一个出口,如果有两个以上割点不用建可以走到另一个连通块里面去。注:连通块指点双连通分量
(3)点双连通分量和边双
点双:如上题:任意两个点存在两条点不重复路径。求的方法:把割点全部算出来再DFS
在跑tarjan的时候和强连通分量一样只是不要把割点给弹栈就可以了
边双:边不重复路径。怎么求:把桥给删了再dfs 也可以和上面一样求。
(感觉dfs更爽欸)
好像一般不考边双)
本文来自博客园,作者:lei_yu,转载请注明原文链接:https://www.cnblogs.com/lytql/p/15003927.html