首页 > 其他分享 >【2024-ZR-C Day 4】图论(1)

【2024-ZR-C Day 4】图论(1)

时间:2024-07-20 14:29:49浏览次数:6  
标签:连通 边双 个点 割边 DFS 2024 Day ZR 分量

1. 强连通分量

1.1. 定义

有向图中,选取一个点集 \(S\),若对于 \(S\) 中的任意两点 \(u, v\),都满足 \(u\) 可以到达 \(v\),则称 \(S\) 是强连通的

强连通分量是图中一个极大的强连通的点集。

性质:把一个有向图通过强连通分量缩点后,新的图是一个 DAG.

1.2. Kosaraju 算法

无向图中,求解连通分量只需要按照 \(1\) 到 \(n\) 的顺序依次考虑每个点。
考虑到 \(i\) 点时,如果 \(i\) 点未被访问过,就说明找到了一个新的连通分量,从 \(i\) 点开始 DFS 即可找到i所在的连通分量。

有向图中,上述算法不成立。

假设 \(A\) 和 \(B\) 是两个不同的强连通分量,且 \(A\) 可以到达 \(B\),那么只有先访问 \(B\),再访问 \(A\),才能使得上述算法成立。
也就是说,遍历顺序要保证 \(B\) 中至少有一个点排在所有 \(A\) 中的点之前。
考虑缩点后得到的 DAG,每次应访问出度为 \(0\) 的点,即按照拓扑序的逆序访问缩点后的所有节点。

Kosaraju 算法的思想:

  1. 把图中所有边反向,再按照 \(1\) 到 \(n\) 的顺序去DFS,到达每个点时将其入栈,得到每个点的出栈序列 \(q_1, q_2, \ldots, q_n\),即为缩点后的拓扑序.
  2. 按照 \(q_n,\ldots, q_1\) 的顺序去 DFS 原图就是一个合法的顺序。

因为把边反向与否不改变强连通分量,所以得到一个简化的算法:

  1. 按照 \(1\) 到 \(n\) 的顺序去 DFS 原图,得到每个点的出栈序列 \(q\).
  2. 按照 \(q_n\ldots q_1\) 的顺序去 DFS 反图,依次得到每个强连通分量。
#include <bits/stdc++.h>
using namespace std;

bool vis[N];
vector<int> g[2][N];
stack<int> stk;

void dfs1(int u)
{
	vis[u] = 1;
	for(auto v : g[0][u])
		if(!vis[v]) dfs1(v);
	q.push(x);
}

void dfs2(int u, int id)
{
	vis[u] = 0, bel[u] = id;
	for(auto v : g[1][u])
		if(vis[v]) dfs2(v, root);
}

int main()
{
	ios :: sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	for(int i = 1; i <= n; i++)
		if(!vis[i]) dfs1(i);
	while(!stk.empty())
	{
		int u = stk.top(); stk.pop();
		if(vis[u]) dfs2(u, ++idx);
	}
	return 0;
}

2. DFS 树

一张图的 DFS 树是在对其进行 DFS 时,所经过的所有有效边形成的树结构。

在构造题中,通常我们用到的是无向图的 DFS 树。

无向图的 DFS 树满足所有非树边都是返祖边


3. 边双连通分量

3.1. 定义&性质

一个无向连通图边双连通,当且仅当对于任意两个点,存在两条不相交的路径。

边双连通分量是图中一个极大的边双连通的点集。

定义割边为:在无向图中,该边所在连通块不再连通的边。
边双连通的定义中,“存在两条不相交的路径”显然等价于“如果无论删去哪条边都不能使它们不连通”,故一个无向连通图边双连通的充要条件是没有割边

一个无向图边双缩点后是一棵树,所有树边是割边。
(若缩点后不是一颗树,说明还存在环,则环上所有的点在一个边双内,这与边双连通分量“极大”的定义矛盾。)

3.2. 算法解析

由【3.1. 定义&性质】,求出所有边双连通分量只需求出所有割边,由割边断开后得到的一个连通块就是一个边双连通分量。

取原图的 DFS 树,只有树边有可能是割边。

一条非树边(由【2. DFS 树】的性质知,只可能是返祖边)会覆盖掉一条链上的树边,这些树边就会被 ban 掉,使用树上差分(或树剖)维护,剩下的边就是割边。


4. Boruvka 算法

一个神秘的 MST 求法。

维护一些连通块(初始都是单点),并进行若干轮连边。

每一轮中,找到每个连通块连向其它连通块的最小边(需要做不等离散化,以边权为第一关键字,以边的编号为第二关键字)并连上,这一条边一定会在 MST 中。
(可以根据 Kruscal 的流程证明。)

每轮连通块数量至少减半,最多进行 \(O(\log n)\) 轮连边。
最劣时间复杂度 \(O((n + m) \log n)\).

Boruvka 算法适合用来求完全图(或非常稠密图)的 MST.


5. 例题

5.1. CF555E Case of Computer Network

给定一张 \(n\) 个点 \(m\) 条边的无向图和 \(q\) 组有向点对 \((s, t)\)。
询问是否存在使得所有 \(s\) 都能到达 \(t\) 的无向图中每条边的定向方案。
\(n,m,q \le 2 \times 10^5\).

有一个显然的结论:

在边双连通分量中可定向,使得内部构成强连通。

只需取边双中的 DFS 树,使树边向下,非树边向上即可。

则在本题中,若 \(s, t\) 在同一边双,则不必考虑(一定可以)。
那么只需考虑 \(s, t\) 在不同边双的情况。

考虑将原图按边双缩点成一颗树。
对于每个询问 \(s, t\),在树上的路径一定为 \(s\) 到根之间向上、根到 \(t\) 之间向下。

可以使用树链剖分+线段树区间覆盖来做,做的过程中 check 当前要定向的边中是否有边已经被定了相反的方向。

5.2. CF1364D Ehab's Last Corollary

给定一个无向连通图和正整数 \(k\),求一个大小为 \(\lceil \frac{k}{2} \rceil\) 的独立集或大小不超过 \(k\) 的环(求出任意一个即可)。

首先找到图中的最小环。

  • 若环的大小不超过 \(k\),则已经得到了解。
  • 若环的大小大于 \(k\):对环进行黑白染色,由狄利克雷抽屉原理,必然存在一个颜色全部相同的大小大于 \(\lceil \frac{k}{2} \rceil\) 的独立集,从其中任选 \(k\) 个点即可。

问题转化为如何求最小环。

对于一条非树边 \((u, v)\),定义 \(w_{u, v} = |dep_v - dep_u|\).
找到图中 \(w\) 最小的非树边,它和 \(u, v\) 之间的所有树边构成最小环。

5.3. CF1103C Johnny Solving

给定一张 \(n\) 个点 \(m\) 条边的无向连通图,以及一个整数 \(k\),保证每个点度数 \(\ge 3\),你需要找到一个至少有 \(\lceil \frac{n}{k} \rceil\) 个点的路径,或者找出 \(k\) 个环,其中每个环的环长都不是 \(3\) 的倍数,且每个环中至少有一个点在这 \(k\) 个环里只出现一次。

任取一棵 DFS 树。

  • 如果最大深度 \(\lceil \frac{n}{k} \rceil\),则找到了路径。
  • 否则,根据树的性质,至少有 \(k\) 个叶子。
    由题中“保证每个点度数 \(\ge 3\)”的限制知,对于每个叶子,其至少有两条返祖边。
    任取其中两条,根据模 \(3\) 的余数分讨后不难发现,一定存在一个包含这个叶子的环,满足其环长不是 \(3\) 的倍数。

5.4. LG5811 [IOI2019] 景点划分

给定一个 \(n\) 个点、\(m\) 条边的无向连通图,以及三个整数 \(a, b, c\),满足 \(a + b + c = n\),你需要将 \(n\) 个点分成三个集合 \(A, B, C\),大小分别为 \(a, b, c\),使得其中至少两个集合是连通的 (集合中的任意两个点能只经过该集合内的点互相到达),或者报告无解。

不妨设 \(a \le b \le c\),则让集合 \(A, B\) 连通的限制一定是最松的。

考虑原图是树的情况。我们想找到一条边,让它两侧的点数分布尽量均匀。

考虑重心,找到所有以重心为根的子树中最大的一个,连接这棵子树与重心的边即为该边。有解当且仅当子树 \(size \ge a\).

标签:连通,边双,个点,割边,DFS,2024,Day,ZR,分量
From: https://www.cnblogs.com/Heartquakes/p/18312678

相关文章

  • C基础(学习)2024.7.19
             Linux基本命令,vi编译器的使用,简单的编程步骤,程序语言,gcc编译器编译过程,进制转换相关知识可以查看文档http://t.csdnimg.cn/CmqhC        数值表示,词法符号,变量,常量相关知识可以查看文档http://t.csdnimg.cn/jJIe2        运算符和输表达式......
  • 2024/7/20周末总结
    本周,我完美完成了PTA基础编程题目集中的函数部分。对阶乘计算的进阶方法这道上周无法通过的题目进行了学习和复现通过。对超大数的输出方式有了新的理解。同时,完成了编程题三分之一的题目,其中,由于BCD数中需要实现位运算而有些难以理解外,其他均以C++通过。关于本周Java的学习,......
  • 【北航主办丨本届SPIE独立出版丨已确认ISSN号】第三届智能机械与人机交互技术学术会议
    由北京航空航天大学指导,北京航空航天大学自动化科学与电气工程学院主办,AEIC学术交流中心承办的第三届智能机械与人机交互技术学术会议(IHCIT2024)将定于2024年7月27日于中国杭州召开。大会面向基础与前沿、学科与产业,旨在将“人工智能”、“智能系统”和“人机交互”等学......
  • 2024暑假集训测试6
    前言比赛链接。挂分挂的最多的一集。T1不知道摩尔投票,被2M内存限制卡死。T2赛时打了个很像正解的莫队,赛时出题人发现了之后现往里加hack,还一个捆绑里加一个,直接爆零了,我真的谢了,求求以后不要一个捆绑放一个hack了,给条活路吧。T3一眼看出线段树优化建图,但是不会打......
  • 2024牛客暑期多校训练营1
    A:ABitCommon题目大意:建立一个长度为n且每个数严格小于\(2^m\)的非空序列A使其存在一个非空子序列B,B中所有元素的与运算结果为1,输出合法A序列的个数。思路:存在子序列合法即该序列合法,其他元素无要求。即可以枚举合法子序列的长度,其他元素均为必定非合法整数。又因为需要结果为......
  • 小欧吃苹果-OPPO 2024届校招正式批笔试题-数据开发(C卷)
    在处理这个问题前,先看一个经典的贪心算法题目。信息学奥赛一本通(C++版)在线评测系统http://ybt.ssoier.cn:8088/problem_show.php?pid=1320注意移动纸牌的贪心策略并不是题目中给出的移动次序:第1堆纸牌9<10,因为是最左侧,它只能从第2堆移动过来一张,这个动作是必须做的(没有别的......
  • [lnsyoj102/luoguP2866]Bad Hair Day
    题意给定序列\(a\),记\(C_i\)为\(a_i\)右侧第一个\(\gea_i\)的元素与\(a_i\)间的元素个数,求\(\sum_{i=1}^nC_i\)sol单调栈可以在\(O(n)\)的时间复杂度内解决求某个元素左(右)第一个大于(小于)的元素。以本题为例,由于本题需要求右侧第一个\(\gea_i\)的元素,因此需要......
  • [lnsyoj110/luoguP2024]食物链
    题意原题链接三类元素\(a,b,c\)满足\(a\tob\),\(b\toc\),\(c\toa\)。现在共有\(n\)个元素,给出\(m\)条关系\(x\toy\)或\(x\)与\(y\)种类相同,输出非法或与前面所属关系相矛盾的关系数量sol并查集可以处理“朋友的朋友是朋友”这样的传递关系,却不能处理“敌人......
  • 大一升大二暑假 NJU暑期课程 Linux系统基础(1) 20240720
    一.操作系统操作系统OperatingSystem简称OS,是软件的一部分,它是硬件基础上的第一层软件,是硬件和其它软件沟通的桥梁。操作系统会控制其他程序运行,管理系统资源,提供最基本的计算功能,如管理及配置内存、决定系统资源供需的优先次序等,同时还提供一些基本的服务程序。Q1:什么是文件......
  • Java学习日记 (day4)
    习题练习1. 输入某年某月某日,判断这一天是这一年的第几天?输入某年某月某日,判断这一天是这一年的第几天packagetest.test2_1;importjava.util.Scanner;publicclassTest_1{publicstaticintsearch_month(intm,int[]arr){if(m==2){......