8.10 睡觉集合与钉耙编程

发布时间 2023-08-11 14:10:18作者: _maze

有时候我们不需要太复杂的结论与算法,只要时间复杂度够就行了。

交朋友

给定 \(n\) 个点和 \(m\) 条有向边。每次可以执行操作:找到 \((p,u)\in E\)\((p,v)\in E\),连 \((u,v)\)\((v,u)\)。问图中最大能有多少条边

后来连的有三种边:

  1. 两条 \(m\) 里的边连起来的。
  2. 一条 \(m\) 里的边加一条新增的边
  3. 两条新增的边

第一种好算。考虑与点 \(u\) 相连的点集 \(V\)\(V\) 中点最终必定两两联通,所以可以把它们用并查集缩成一个点。

之后我们把所有缩过的点放在一起 \(bfs\),当发现点集 \(V\) 有连向 \(p\) 的出边,则将 \(p\) 及其所属集合加入点集 \(V\)。因为此时 \(p\) 对集合 \(V\) 中的每个点都满足操作条件。

知道的点集以后,算边数是简单的。要注意原有的有向边不能重复算。