【持续更新】做题回顾和总结
【持续更新】做题回顾和总结
- 2023/8/16 10:34
遗留问题:1.无权无向图上简单最长路怎么找?2.有向图最小环怎么找?如果有环套环之类的,DFS可以吗?
- 2023/8/16 9:16
如果一个图所有点出度都为1,那么每个点要么在环内,要么在环外并且可以到达环。处理的时候,先 toposort,把非环内的外围的点删掉。然后处理环,最后处理外围的点。
toposort 是一种把 DAG 补成序列的操作。我认为这不是压缩,而是补,因为序列是一个填满了的 DAG。可以证明,\(n\) 个点的简单图 DAG(不含重边和自环)边数最多应该是 \(\frac{n(n-1)}{2}\),刚好是序列情况。
- 对于 \(n\) 个点的简单无向图,边数最大是 \(\frac{n(n-1)}{2}\)。当变成有向图时候,每一个无向边只能选择一个方向,如果有两个方向,那么就会形成环。因此不会多于这个边数。然后显然可以构造等于这个边数的案例。
转化成序列可以利用相关性质,以及这个拆点过程可以利用。
(这一条什么时候可以单发一篇)
- 2023/8/15 9:30
AT_utpc2013_03 直径
循环字母不冲突
及时清空
距离是最小值,直径是距离最大值 ,有两点,因此拆开枚举
记得+1
j下标
关于无权无向图的最短路,直接 BFS 是 O(m+n) 的复杂度级别,
比 Dijkstra 少一只优先队列的 log,原因就是没有权重。
那么多源最短路就是 O(n * (n + m)) ,弗洛伊德是 O(n^3),多次 Dijkstra 是 O(n * (n + m)logm),多次SPFA是O(nkm)。
这差的一个次方在于这个图比较稀疏,m 没到 n 的平方。
可以看出,图越简单,对应的算法时间复杂度越低。
Floyd负环可以二倍常数,再跑一遍看看有没有变。注意Inf。
和边有关的最短路算法是 Dijkstra,SPFA
无关的是 Floyd,bellman-ford(O(nm)),
SPFA是队列优化之后把 n 打成 k。
最小生成树Prim O(n^2),krushkal 复杂度O(mlogm)
一个适合稠密,一个适合稀疏。但是在无向无权图中,
只要联通即可。
因为信息量少。
这道题做法首先先想到枚举边,跑最短路,
时间复杂度O(n1*n2*n*(n+m))。
然后我们发现可以分开算,因为两个联通块之间只有一条边。
那么要么是之间,要么是之内。
之间枚举发现重复用,所以一次就够。
因此O(n*(n+m) + n1*n2)
- 2023/8/14
最近在做树和图相关的题目。中间碰到过很多关于 vis 数组的运用。这里总结一下。
vis 数组分成两种,一种是函数调用前 vis,return 的时候再取消。这样是枚举不同的 dfs 路径,在一个节点下面的所有孩子跑递归。
另外一种是全局 vis, vis 过一遍就不用再vis了。这里注意vis的位置,下面会提到。
对于树上问题,无论是 BFS 还是 DFS,怎么vis都行,无论是全局还是路径搜索。甚至不需要 vis,直接判断是否是父节点,然后 continue 掉就行(注意所有的 continue 之前要重复一边一般的结束条件)。
对于图上问题,要分情况,看是哪一种。注意,DFS 不介意在 kids 那里变 true 还是在递归的开始处。但是 BFS 是有问题的,一般来讲要在 kids 那里就把 vis 变 true,因为放入队列会有延迟处理,本来要被 vis 的没有被判掉。
对于二分图,是多次全局 vis,然后每次清零。不要写成随问随清,因为这样会变成搜索,就挂了。vis 必要的记录是记录右侧(当以左侧为开始)。都记录是可以的。可以不去重边。
无论什么样的 vis,都要结合实际情况和效果,在脑海里面过一遍,或者拿笔画一画,看看是不是自己想要的效果。无论什么问题,都要注意 vis 和其他配套数组的初始化。
优先队列优化的目的是只有一遍。不然复杂度和普通队列无异,毕竟有 vis 配合。
要注意赋值前后关系。包括 if else,赋值后打不打 else 的问题。
P1330 封锁阳光大学
这道题是黄题,但是想着写二分图,但是是错的。
区分奇环,然后转化成二分图。
但原因就是二分图可以有相邻点,只是一条匹配边上不能相邻,边边之间是可以的。
不同方向的簇是可以相连的,根根相连。
比如这个例子:
1 2
1 3
4 5
4 6
4 7
1 4
站在1 4两个位置上就可以完成最小匹配。但是这显然相邻,不符合这道题意。
转化成二分图之后,原题答案就是每个连通块一侧的最小值之和。
考虑联通块内,显然不同。我们构造二分图点覆盖方案时候专门要选两边。
这道题没有推理出来,原因就是没有拿这个道的元素和条件进行尝试。
就像树要找子树、根这些结构,图要看点、边、环。
因为每一条边都只能连一个点,那另外一个点就一定不选,再连出去,就形成染色了。
黑白一起判断的原因是,这个方案的不选就是相反方案的选,和棋盘格一样,信息同时包含的神奇。
因为是黑白染色,所以分为两类,出发类一样,最终选的就一样。这奇偶转换的特性所致。
调代码记得检查、全面、看TODO、清空、数组边界。要肯花这个脑力,这样效率最高,不然枉费时间。
比如写循环写一段要看一下continue,写条件看赋值顺序,要对一般情况进行分类讨论枚举,要想清楚过程。