图论

最短路:\(k\) 短路,差分约束,最短路图。(两天)
生成树:最小生成树,最优比率生成树,最小瓶颈生成树(两天)
欧拉回路(一天)
Dinic,费用流,分数规划

连通性问题

边双

边双连通是一个等价关系,边双连通分量就是其划分的等价类。
对于一条边,如果删去后 \(G\) 的连通块数量增多了,我们称它是。把所有桥边删除后剩下的连通块一定是边双连通分量(不存在桥),而它们在原图中是极大的(删桥可以让它们不连通),因此转化成找桥。在 dfs 树上考虑,无向图 dfs 树只有树边和返祖边。然后一般有两种方法:

  1. 我们发现每个返祖边,其对应一条“不拐弯”的简单树上路径,而这个路径上的边都一定不是桥,把这些边打上标记,最后没有标记的边就是桥边,用差分维护标记可以做到 \(O(n+m)\)
  2. 从 tarjan 算法考虑,我们定义 \(dfn_u\) 表示 dfs 时访问 \(u\) 的时间戳, \(low_u\) 表示以 \(u\) 为根的子树内所有点,在经过一次返祖边后能到达的点中 \(dfn\) 的最小值。此时如果对于树边 \((u,v)\)\(dfn_v=low_v\) 是该边是桥的充要条件。求 \(low\) 可以在 \(dfs\) 过程中求出:对于树边 \((u,v)\),我们用 \(low_v\) 更新 \(low_u\);否则用 \(dfn_v\) 更新 \(low_u\)。然后可以对所有桥打标记并再次 dfs 对所有在一个边双内的点染色(或者也可以类似点双用栈维护,避免第二次 dfs)
P8867 [NOIP2022] 建造军营

缩边双,一个边双内部,军营和道路都可以随便选,军营数看做每个点的权值 \(c\)(道路单独拎出来后面算)。
选择一些点后,树上构成的最小联通树内部边必须选,其他边随便选。设方案为 \(S\),共 \(k\) 条边,则贡献为 \(2^{m-k}\prod_{u\in S}2^{c_u}-1\)

\(dp_u\) 表示对于所有点都在 \(u\) 子树中的方案 \(T\),其贡献为点权乘积乘 \(\frac{1}{2}\) 的边数次方,并且钦定选 \(T\) 中的 LCA 点 \(t\)\(u\) 的路径上的边(可以不选点 \(u\))。
那么有转移式 \(dp_u=2^{c_u}\prod_{v\in son(u)}(1+\frac{1}{2}dp_v)-1\),最后 \(-1\) 是为了删去空方案。
算出 \(dp\) 后,考虑统计答案,枚举每个方案的 LCA 为 \(u\),则如果选 \(u\) 点,则贡献就是 \((2^{c_u}-1)\prod_{v\in son(u)}(1+\frac{1}{2}dp_v)\),如果不选 \(u\) 点,那么需要至少选两个子树才能满足 LCA 为 \(u\),这部分贡献为 \(\prod_{v\in son(u)}(1+\frac{1}{2}dp_v)-1-\sum_{v\in son(u)}\frac{1}{2}dp_v\)。时间复杂度 \(O(n)\)

点双

点双连通并不是等价关系(若 \(x,y\)\(y,z\) 都点双连通,但是在删掉 \(y\) 之后 \(x,z\) 可能不连通)。
但是我们可以定义割点:在删除该点后 \(G\) 的连通块使数量增多的点。
在 dfs 树上考虑,对于一条树边 \((u,v)\),如果 \(low_v\ge dfn_u\),那么在删除 \(u\) 之后子树 \(v\) 以及 \(u\) 的祖先(或者 \(v\) 的兄弟)必然被分成了两个部分,此时 \(v\) 就是割点,如果 \(u\) 是根节点那么 \(v\) 必须有兄弟 \(u\) 才是割点。
由此我们可以容易的找出所有的割点,而点双就是从某个割点开始向下 dfs,每次遇到割点就不去会被割开的子树所形成的结构,我们可以用实时维护这个东西做到 \(O(n+m)\)

重要性质: 点数大于 \(2\) 时,点双中任何两点间都存在两条不相交路径(都包含在一个简单环上)。
证明:这是可以用定义得到的,因为如果不存在两条路径则一定可以构造出割点,同时这两条路径的并就是简单环。
这个性质证明虽然容易,但是在把问题转化成点双时这非常常见!
其他性质:

  1. 所有割点至少在两个点双当中,非割点仅在一个点双当中。
  2. 每个边恰好属于一个点双
证明 先用 dfs 树的构造证明点双的唯一性。

所有非割点的导出子图的每个连通块都是点双,然后依次加入割点,假设当前加入点 \(u\),考虑所有边 \((u,v)\),如果 \(v\) 是割点,那么 \((u,v)\) 就是一个点双(显然不能再加入更多点);否则 \(u\) 可以加入 \(v\) 原来所在的那个点双。由于 \(u\) 是割点,则 \(deg_u\ge 2\),因此割点在至少两个点双中。

代码
void tarjan(int u, int fa) {
	if (adj[u].empty()) {
		vdcc[++vcnt] = {u};
		return;
	}
	dfn[u] = low[u] = ++cur;
	stk[++top] = u;
	for (auto v : adj[u]) {
		if (v == fa) continue;
		if (dfn[v]) low[u] = min(low[u], dfn[v]);
		else {
			tarjan(v, u);
			low[u] = min(low[u], low[v]);
			if (low[v] >= dfn[u]) {
				vcnt++;
				int x;
				do {
					x = stk[top--];
					vdcc[vcnt].push_back(x);
				} while (x != v);
				vdcc[vcnt].push_back(u);
			}
		}
	}
}

圆方树

一种把图结构转化成树结构以方便维护或者查询的算法。
下面称原图为 \(G\),其所对应的圆方树为 \(T\)
对于一个 \(n\) 个点,\(c\) 个点双连通分量的图 \(G\),我们对原图每个点建一个圆点,每个点双建一个方点,对于每一个点双连通分量,它对应的方点向这个点双连通分量中的每个点连边,这样形成的树成为圆方树。
其总点数为 \(n+c\),而 \(c\le n\),因此数组开到 \(2n\) 即可。
构建圆方树直接调用求点双的代码即可。

重要性质:对于两个圆点 \(u,v\),则 \(u,v\)\(G\) 中所有简单路径的并集等于 \(u,v\)\(T\) 中简单路径上的方点的邻域的并集。

证明 我们先证明一个点双的重要性质:对于图 $G$,其中某个点双内的任意两点 $u,v$,所有 $u$ 到 $v$ 的路径的并等于这个点双。

首先所有 \(u\)\(v\) 的路径一定包含在这个点双内,因此我们只要证明对于点双内的任意三点 \(x,y,z\),存在一条由 \(x\)\(y\) 途径 \(z\) 的路径。下面的证明来自小粉兔的博客

  • 考虑构造一个网络流图,源点向 \(z\) 连一条容量为 \(2\) 的边,\(x,y\) 向汇点连一条容量为 \(1\) 的边。对于原图中的边 \((u,v)\)\(u\)\(v\)\(v\)\(u\) 分别连一条容量为 \(1\) 的边。然后再对除了 \(z\) 每个点拆点:\(u\) 拆成 \(u_1,u_2\)\(u_1\)\(u_2\) 连容量为 \(1\) 的边。显然这样构造的最大流 \(\le2\),另一方面,如果最小割 \(=1\),说明我们可以割一条边就让源点和汇点不连通,考虑如果割拆出来的边,那么相当于删了一个点,不改变连通性。如果割一条原图中的边 \((u,v)\),这弱于删一个点,因此必然也不改变连通性。因此最小割 \(\ge 2\)。根据最大流最小割定理,\(\text{最大流}=\text{最小割}=2\)。意味着找到 \(z\)\(x\)\(z\)\(y\) 两条不交路径,证毕。

回到原命题,考虑 \(G\) 中所有的简单路径在对应到圆方树上都不会走出这个邻域,又根据上面的性质我们能覆盖邻域中的每个点,因此相等。

ABC318G Typical Path Problem

只要判断 \(B\) 是否在 \(A\)\(C\) 中方点的邻域中,暴力即可(事实上等价于 \(dis(A,B)+dis(B,C)-dis(A,C)\le 2\),用 \(O(n)-O(1)\) RMQ 可以做到 \(O(n+q)\))。
代码

P4630 [APIO2018] 铁人两项

建出圆方树,定义 \(f(u,v)\) 表示圆方树上 \(u\)\(v\) 的路径中方点邻域点数,要求的就是 \(\sum_{i,j\le n,i\neq j}f(i,j)\),我们令方点权值为其度数(代表的点双的大小),圆点权值为 \(-1\),那么 \(f(u,v)\) 就是 \(u\)\(v\) 路径的权值和,把贡献拆开到每个点上,转化成统计经过一个点的路径数,分子树内/子树外讨论即可,时间复杂度 \(O(n)\)
代码

P4606 [SDOI2018] 战略游戏

删的点一定要是割点,考虑建出圆方树,发现 \(S\) 中所有点在圆方树中的最小连通图内的圆点都是合法的。因此答案就是该图的圆点个数 \(-|S|\)
求该图的圆点个数可以把圆点 \(u\) 的权值放到边 \((u,fa_u)\) 上,然后套用 P3320 做法即可,点 \(r\) 要特判。
注意排序时要按照圆方树的 dfn 排序,不要写成原图的 dfn 序了。
代码

强连通分量

2-SAT

图论杂题

P3320 [SDOI2015] 寻宝游戏

结论:树上点集 \(\{a_1,a_2,\cdots, a_n\}\) 构成的最小连通子图的边权和为 \(\frac{\sum_{i=1}^{n}dis(a_i, a_{i+1})}{2}\)(其中 \(a_i\) 按照 dfs 序排序,且 \(a_{n+1}=a_1\))。

证明 称原树为 $T$,新树为 $T'$,设 $r=LCA(a_1,a_2,\cdots, a_n)$,考察对 $T$ 做 dfs 的过程中对 $T'$ 的访问:从 $r$ 开始,先走到 $a_1$,再回退到 $LCA(a_1,a_2)$,再走到 $a_2$,再回退到 $LCA(a_2,a_3)$,再走到 $a_3$,$\cdots$,这样最后走到 $a_n$,再回到 $r$。总距离和为 $dis(r,a1)+\sum_{i=1}^{n-1}dis(a_i,a_{i+1})+dis(a_n,r)$,由 $LCA$ 的欧拉序区间最小深度的意义可知 $r=LCA(a_1,a_n)$,因此总距离和就是 $\sum_{i=1}^{n}dis(a_i, a_{i+1})$。由于在 dfs 的过程中,$T'$ 的每条边会被访问两次(一进一出),因此 $T'$ 边数为 $\frac{\sum_{i=1}^{n}dis(a_i, a_{i+1})}{2}$

于是维护按 dfs 序排序的点集,每次更新点只涉及到该点的前驱和后继,set 即可。
代码

posted @ 2023-09-27 19:27  71rats  阅读(7)  评论(0编辑  收藏  举报