学图论

news/2024/11/13 19:18:16/文章来源:https://www.cnblogs.com/laijinyi/p/18544589

Boruvka

每一轮操作,对于每个点来说,让他和“最近的与他有连边且还未连通的点”相连。

最多 \(\log n\) 轮,每轮 \(O(n\cdot p)\)\(p\) 为找“最近的与他有连边且还未连通的点”的复杂度。

\(O(np\log n)\)

Kruskal 重构树

设从小到大加边,性质:

  • 二叉树,\(2n-1\) 个点(数组开两倍)
  • 原图的节点对应树中的叶子
  • 若忽略叶子,重构树满足堆的性质,即父亲 \(\ge\) 儿子
  • \(u,v\) 之间所有路径的“经过边权最大值”的最小值,是 \(u,v\) 在重构树上 LCA 的权值
  • 原图 \(u\) 点,其只经过 \(\le w\) 的边能到达的点,为 \(u\) 在树上最高的权值 \(\le w\) 的祖先的子树内所有叶子,找到这个点可倍增。

他的性质比原图最小生成树的性质,要好得多。

同余最短路

问题:给定一些数 \(a_i\),求某范围内的数有多少数可用 \(a_i\) 完全背包得出。

\(r\) 能被表示出,则 \(r+k\cdot a_i\) 也能被表示出,故固定一个 \(a_t=m\) 作为模数,对 \(x\in[0..m-1]\) 算最小的能被凑出的 \(p\equiv x\pmod m\) 是多少。

建图:对所有 \(i\)\(x\to(x+a_i)\bmod m\) 连权值为 \(a_i\) 的边,跑最短路即可得出所求。

转圈做法:考虑模 \(m\) 意义下的完全背包,考虑新加入一个 \(a_i\),显然他在长度为 \(m\) 的环上形成 \(\gcd(a_i,m)=d\) 个子环,对每个子环分别顺序转移两圈即可;或者从子环上权值最小的点开始顺序转移一圈即可(写起来不如前者简洁)。\(O(nm)\)

个人觉得转圈做法更自然。

Johnson

多源最短路,支持负边,\(O(nm\log m)\)

考虑对每个点 \(i\)\(h_i\),令 \(w'(u,v)\gets w(u,v)+h_u-h_v\),求出新图 \(s\to t\) 最短路后减去 \(h_s-h_t\) 即可求出原图最短路。

列出条件:\(w(u,v)+h_u-h_v\ge 0\),即 \(h_u+w(u,v)\ge h_v\),发现令 \(h_u\)\(d_u\) 即可。

故令 \(w(S,i)=0\),跑 SPFA(顺便判负环),改边权得新图后跑 \(n\) 次 Dijkstra 即可。

最短路树

\(v\) 的最短路是由 \((u,v)\) 松弛而来,则在生成树中保留 \((u,v)\)

性质:树上 \(s\to v\) 的路径长度为 \(s\to v\) 的最短路。

最短路图

\((u,v,w)\) 满足 \(dis_u+w=dis_v\),则保留这条边。

相当于对每个点 \(v\) 保留图上所有 \(s\to v\) 的最短路。

性质:

  • \(dis\) 定向后是个 DAG
  • 他的所有生成树都是最短路树

\(dis(s,u)+w+dis(v,t)=dis(s,t)\),则 \((u,v,w)\) 可以在 \(s\to t\) 的最短路上。

欧拉回路

看代码就懂了。

int tp, stk[N];
void Eul(int u) {for (int &i = cur[u]; i < (int)G[u].size(); ) Eul(G[u][i++]);stk[++tp] = u;
}Eul(s);
while (tp) cout << stk[tp--] << ' ';
cout << '\n';
  • 欧拉路径:一笔画
  • 欧拉回路:一笔画,起点等于终点
  • 欧拉图:存在欧拉回路
  • 半欧拉图:存在欧拉路径,但不是欧拉图

欧拉图判定:

  • 有向图:弱连通,入度等于出度
  • 无向图:连通,每个点度数为偶数

半欧拉图判定:

  • 有向图:弱连通,存在两个点入度分别等于出度加一、出度减一,其余点入度等于出度
  • 无向图:连通,恰好两个点度数为奇数

连通性

\(\text{low}(u)\)\(u\) 子树内能一步走到的最小 dfn

  • 边双:割边,每个点恰属于一个边双连通分量
  • 点双:割点,每条边恰属于一个点双连通分量

Menger 定理:

  • 边形式:使 \(u,v\) 不连通所需删去的边数最小值,等于 \(u,v\) 之间边不交的路径的数量的最大值。
  • 点形式:使 \(u,v\)(不相邻)不连通所需删去的点数最小值,等于 \(u,v\) 之间点不交(不含 \(u,v\))的路径的数量的最大值。

证明可以看 Alex-Wei 的。这个定理与最大流-最小割定理类似。

于是我们可以定义:

  • 局部边连通度:使 \(u,v\) 不连通所需删去的边数最小值;
  • 局部点连通度:使 \(u,v\) 不连通所需删去的点数最小值(\(u,v\) 不相邻);
  • \(k\)-边连通:\(u,v\) 边连通度 \(\ge k\)
  • \(k\)-点连通:\(u,v\) 点连通度 \(\ge k\)

圆方树

普通圆方树是只支持仙人掌的;这里默认的圆方树是广义圆方树。

建法:若 \(\text{low}(v)\ge\text{dfn}(u)\),说明 \(v\) 子树在栈内的部分与 \(u\) 形成了点双,新建方点并连边、弹栈直到 \(v\) 被弹出即可,注意两倍空间。

圆方树完整保留了原图的必经性。

支配树

对于有向图,若 \(s\to y\) 的所有路径均经过 \(x\),则称 \(x\) 支配 \(y\)

由于支配关系具有

  • 传递性:若 \(x\) 支配 \(y\)\(y\) 支配 \(z\),则 \(x\) 支配 \(z\)
  • 自反性:\(x\) 支配 \(x\)
  • 反对称性:若 \(x\) 支配 \(y\)\(y\) 支配 \(x\),则 \(x=y\)

这保证了支配是偏序关系,这让他能建出 DAG,但不够优秀。

性质:若 \(x,y\) 均支配 \(z\),则 \(x,y\) 之间也有支配关系。

注意到这样就可以建树了:考虑支配 \(y\) 的所有点 \(D_y=\{x_1,x_2,\ldots,x_k\}\),则 \(D_y\) 内所有元素形成了全序关系,即任意两个元素之间均可比较,所有 \(x_i\) 的关系可以用一条链描述,这就是 \(y\) 的祖先链。

\(f(i)\) 表示 \(D_i\) 当中被其他所有点支配的 \(x_j\),在 \(i\)\(f(i)\) 之间连边,这就是支配树。

支配树用于描述有向图在给定起点时节点的必经性。

对于 DAG,我们可以 \(O((n+m)\log n)\) 求出其支配树:

按拓扑序处理,若 \(x\) 有入边 \(y_i\to x\),则

\[ f(x)=LCA(y_1,y_2,\ldots,y_k) \]

动态更新倍增数组即可。

DAG 链剖分

若原图有若干无入度点,新建 \(1\) 向他们连边,这样只有 \(1\) 没有入度。

\(f(i)\) 为从 \(i\) 出发的路径条数。定义重儿子为 \(f\) 值最大的后继,这样对于任意轻边 \(i\to j\)\(2f(j)\le f(i)\)。这可以解决部分题目,但不够优秀,我们想要 \(i\to son(i)\) 形成的是链而不是树。

\(g(i)\)\(1\to i\) 的路径条数。设 \(i\to j\) 为重边当且仅当 \(j\)\(i\)\(f\) 值最大的后继,且 \(i\)\(j\)\(g\) 值最大的前驱。这样形成了若干条链。走一条轻边,要么 \(f\) 减半,要么 \(g\) 翻倍,故一条路径上的轻边条数为 \(\log V\) 级别,\(V\) 为总路径条数。这说明只有当路径条数不大时 DAG 链剖分才适用

DAG 链剖分常与 SAM 结合,因为此时路径条数为 \(s\) 的本质不同子串数,为 \(O(n^2)\) 级别,且剖分后可以快速定位字符串查询相关信息。更重要的是可以通过 \(\log\) 条时间戳连续的链描述 \(s[l,r_1]\)\(s[l,r_2]\) 的路径,非常有用。

Dilworth 定理

一个偏序集的最大反链大小等于其最小链覆盖。

考虑一个长度为 \(n\) 的排列 \(p\)。以下两个结论至少有一个成立:

  • 存在一个长度为 \(\sqrt n\) 的递增序列
  • 存在一个长度为 \(\sqrt n\) 的递减序列

Hall 定理

设一个二分图的两部点数为 \((x,y),x<y\),其的一个完美匹配定义为左部 \(x\) 个点成为匹配点。

该二分图存在完美匹配的充要条件是,对于左部点的大小为 \(k\) 的任意子集 \(S\),这些点在右部点连到的点集(也被称为 \(S\) 的邻域,记为 \(N(S)\))大小不小于 \(k\)

推论:一个任意二分图 \((V,E)\) 的最大匹配为

\[ |V|-\max_{S\subseteq V}\{|S|-|N(S)|\} \]


习题会添加在这里面,附带简要题解。

题目选做

1. CF1965F Conference

Statement

二分图匹配,但是左边每个人连向的都是一段区间,\(\forall k\in[1..n_1]\),输出从右边点选任意长度为 \(k\) 的区间和左边所有人做匹配,匹配数能达到 \(k\) 的区间的个数,\(n_1,n_2\le2\cdot10^5\).

Solution

判断右边点单个区间 \([l,r]\),考虑 Hall 定理,设 \(N(S)\) 为右边点 \(S\) 对应的左边点集大小,\(S\) 合法当且仅当 \(|N(S)|\ge|S|\),那么 \([l,r]\) 合法当且仅当 \(\forall S\subseteq[l,r],S\) 合法.

猜测只用判断成一段区间的 \(S\),但是会被以下数据叉掉:

3
1 3
2 2
2 2

对于 \([1,3]\),只有 \(\{1,3\}\) 不合法.

于是考虑处理初始的左边点的线段,发现对于 \([a,b],[a,c](b\le c)\),把他们换成 \([a,b],[a+1,c]\) 不影响结果(\(a=b=c\) 时相当于删掉这条线段),因为对于 \(a\) 点,为了最优,他一定会选 \([a,b]\) 而非 \([a,c]\).

处理后每个人的左端点互不相同,此时找性质,发现:

  • 可以只判成一段区间的 \(S\),因为若一个不合法的 \(S\) 不是一段连续的区间,考虑将其补全成一段区间,此时他还是不合法,因为每补全一个数,\(|N(S)|\) 至多增加 \(1\),此时有只包含这个数的区间.
  • 看单调性,发现若 \([l,r]\) 不合法,\([l,r+1],[l-1,r]\) 也不合法,因为 \([l,r]\) 合法当且仅当 \(\forall S\subseteq[l,r],S\) 合法.

于是可以双指针求,对每个 \(l\) 最大的 \(r\) 使 \([l,r]\) 合法,最后差分统计即可.

Code
// LUOGU_RID: 160078999
// by:Joey_c / sto hunction orz
#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define reo(i,j,k) for(int i=j;i>=k;i--)
#define debug fprintf(stderr,"Running %s on line %d...\n",__FUNCTION__,__LINE__)
#define fi first
#define se second
#define pb emplace_back
#define mp make_pair
typedef long long ll;
constexpr int N=2e5+10;int main() {ios::sync_with_stdio(false), cin.tie(nullptr);int n,m=0,nn;cin>>n,nn=n;vector<pair<int,int>>a(n+1);vector<int>buc[N];rep(i,1,n)cin>>a[i].fi>>a[i].se,m=max(m,a[i].se),buc[a[i].fi].pb(a[i].se);n=0;priority_queue<int,vector<int>,greater<int>>q;rep(i,1,m){for(int j:buc[i])q.push(j);while(!q.empty()&&q.top()<i)q.pop();if(!q.empty())a[++n]=mp(i,q.top()),q.pop();}vector<int>b(m+2,0),c(m+2,0),ans(max(m,nn)+2,0);rep(i,1,n)b[a[i].fi]=1,++c[a[i].se];for(int s=0,l=m,r=m;l;--l){s+=c[l];while(r>=l&&s<r-l+1)s-=b[r--];if(r<=m)++ans[r-l+1];}reo(i,max(m,nn),1)ans[i]+=ans[i+1];rep(i,1,nn)cout<<ans[i]<<"\n";return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/833089.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

团队作业4——项目冲刺-1-第二篇

团队作业4——项目冲刺-1-第二篇这个作业属于哪个课程 <计科22级34班>这个作业要求在哪里 <作业要求>这个作业的目标 修改完善需求规格说明书、系统设计、Alpha任务分配计划、测试计划GitHub 链接 https://github.com/tangliweiwww/ChatGpt🍟一、团队 1.团队名称…

[Paper Reading] Fusing Monocular Images and Sparse IMU Signals for Real-time Human Motion Capture

目录名称TL;DRMethodLocal Pose EstimationRNN-P1RNN-P2RNN-P3Global Translation EstimationRNN-T1RNN-T2RNN-T3Hidden State Feedback MechanismExperiment效果可视化总结与发散相关链接 名称 link 时间:23.09 作者与单位:主页: https://github.com/shaohua-pan/RobustCap…

HarmonyOS Next 入门实战 - 创建项目、主题适配

​开发一个简单的demo,其中涉及一些鸿蒙应用开发的知识点,其中涉及导航框架,常用组件,列表懒加载,动画,深色模式适配,关系型数据库等内容,在实践中学习和熟悉鸿蒙应用开发。 ​​ ​​ 首先下载并安装DevEco Studio开发环境,下载完成后按照提示安装即可,过程不在多说…

rust学习八、包和模块

总体上,也没有什么特别的地方,和其它语言比较起来。 我们可以看懂熟悉的字眼:包括、模块、use、公共等等 如果是英文,则需要知道crate、pub。 本章节对应相关书籍的第七章节. 一、一个rust可执行程序的大体结构 就本章节而言,尚未接触到一个非常复杂的工程结构,据说有什么…

starrycan的pwn学习记录1

一.Introducation 0x01 简介CTF 0x02 什么是pwn ”Pwn”是一个黑客语法的俚语词,是指攻破设备或者系统 。发音类似“砰”,对黑客而言这就是成功实施黑客攻击的声音--砰的一声,被“黑”的电脑或手机就被你操纵了。 CTF中的pwn CTF中的PWN主要是针对于二进制漏洞挖掘与利用,通…

计算机组成原理与操作系统 第二章 处理机组成与管理

目录1.CPU的功能和组成1.1CPU的四大功能1.2CPU的基本组成1.3 一条指令如何在CPU内运行2.指令系统2.1机器语言与指令2.1.1基本概念2.1.2一条指令一般应包含的信息2.1.3指令的类型与功能2.1.4寻址方式2.2指令格式的设计2.2.1基本概念2.2.2指令类型2.2.3操作码类型2.2.4指令设计2.…

UWB无线通信技术

UWB定位与通信技术标准第2章 UWB无线通信技术 UWB(超宽带)技术最早诞生于无线通信领域,该新兴技术一出现就备受关注UWB信号有着极大的带宽,其时间分辨率高、抗多径效应能力强,被认为是高速率短距离无线通信中具有很强竞争力的候选方案之一为此,本章寻根溯源,从UWB无线通…

极速启动,函数计算弹性降本能力再升级

本文将深入探讨函数计算如何通过技术革新实现提效降本,以及其在 AI 业务、数据处理和 Web 应用等多个领域的广泛应用。作者:墨飏 在数字化转型的大潮中,云计算成为推动创新和优化业务流程的关键力量。作为阿里巴巴集团的核心产品之一,函数计算(Function Compute)引领着 S…

用函数实现模块化程序设计四

数组作为函数参数数组作为函数参数 调用有参函数时,需要提供实参,实参可以是常量、变量或表达式 数组元素的作用与变量相当,一般来说,凡是变量可以出现的地方,都可以用数组元素代替,因此,数组元素也可以用作函数实参,其用法与变量相同,向形参船体数组元素的值。此外,…

Vulnhub W1R3S: 1.0.1

Vulnhub W1R3S: 1.0.1 0x01:端口扫描 主机发现,靶机ip:192.168.231.133 nmap -sn 192.168.231.0/24-sn 仅主机扫描 /24 扫描c段详细全端口扫描 nmap -sT -sC -sV -O -p21,22,80,3306 192.168.231.133 -oA /root/scan/1/-sT: 以TCP进行扫描; -sC:使用 nmap 的默认脚本集合进…