一种 DAG 上可达性判定问题的解决方案

news/2025/12/7 19:21:11/文章来源:https://www.cnblogs.com/zifanoi/p/19318662

1. 问题简述

给定一个有向无环图 \(G=(V,E)\),记 \(n=|V|\)\(m=|E|\)。有 \(q\) 次查询,每次给定两个点 \(a\)\(b\),判断是否存在一条以 \(a\) 为起点,\(b\) 为终点的简单路径。

其中 \(n,m\) 同阶,保证 \(\forall (u,v)\in E,u<v\)

(容易用 bitset 做到 \(\mathcal O(\frac{nm}w+q)\)

1.1 任意图

去除 DAG 的限制,即给定的图为任意有向图。此时进行一次缩点,即可转化为 DAG 问题,本质上是一样的。

1.2 树

限制给定的图是树的形态,则可以构造 dfn 序,容易做到 \(\mathcal O(n+q\log n)\)

2. 定义

2.1 有向无环图(DAG)

\(G=(V,E)\) 是一个有向图,其中:

  • \(V\) 为顶点集合。
  • \(E\subseteq V\times V\) 为有向边集合。

我们称 \(G\) 是一个有向无环图(DAG),若 不存在 长度大于等于 \(1\) 的顶点序列 \(v_0,v_1,\dots,v_k\) 使得 \(\forall i\in [0,k-1]\cap\mathbb{Z}, (v_i,v_{i+1})\in E\)\(v_0 = v_k\)

即不存在从某个点出发又回到自身的有向路径

2.2 搜索树(有向根树 / arborescence)

\(S=(V,E_S,r)\)\(G\) 的一个搜索树(有向根树),当且仅当:

  • \(E_S\subseteq E\)
  • 在有向图 \((V,E_S)\) 中,\(r\in V\) 为根,并且对于任意顶点 \(v\in V\setminus\{r\}\),存在且唯一一条由 \(r\) 出发、沿着 \(E_S\)有向路径到达 \(v\)
    (等价地,每个 \(v\ne r\)\(E_S\) 中有且只有一条入边,且 \((V,E_S)\) 无有向环。)

我们有时把这样的结构也称为以 \(r\) 为根的有向生成树(arborescence)

2.3 树剖(暂时没有用到)

先将有向树转为无向以便树剖定义:

树剖通常定义在无向图上。为此对 \(S\) 定义其对应的无向化(忽略方向):

\[\operatorname{und}(S)=\bigl(V,\,E_S^{\mathrm{u}}\bigr),\qquad E_S^{\mathrm{u}}=\{\{u,v\}\mid (u,v)\in E_S\}. \]


\(T=(I,F)\) 为一棵树,包函数为 \(\chi: I\to 2^V\)。则称 \((T,\chi)\) 为图 \(\operatorname{und}(S)\) 的一个树剖当且仅当下面三条成立:

  1. 覆盖:\(\bigcup_{i\in I}\chi(i)=V\)

  2. 边被包含:对任意无向边 \(\{u,v\}\in E_S^{\mathrm{u}}\),存在 \(i\in I\) 使得 \(\{u,v\}\subseteq\chi(i)\)

  3. 连通性/子树性质:对任意顶点 \(v\in V\),集合 \(\{\,i\in I\mid v\in\chi(i)\,\}\) 在树 \(T\) 中构成一个连通子树。

树剖的宽度定义为

\[\mathrm{width}(T,\chi)=\max_{i\in I}|\chi(i)|-1. \]

2.4 DFS 序

设给定搜索树(有向根树)

\[S=(V,E_S,r) \]

其中 \(r\) 为根,且对任意 \(v\ne r\)\(E_S\) 中有且只有一条入边(即每个顶点有唯一父亲)。

\(n=|V|\)


定义一个排列(序列)

\[\pi:\{1,2,\dots,n\}\to V \]

满足 \(\pi\) 是双射。将 \(\pi\) 称为一个 DFS 序,其中 \(\pi(k)\) 表示第 \(k\) 个被首次访问的顶点。

定义顶点的 dfn 值为

\[\mathrm{dfn}:V\to\{1,2,\dots,n\},\qquad \mathrm{dfn}(\pi(k))=k. \]

于是

\[\pi(\mathrm{dfn}(v))=v,\qquad \mathrm{dfn}(\pi(k))=k. \]

3. 解决方案

本文探讨一种类似树剖的做法,构造某种 DFS 序将问题简化。

3.1 整体思路

构造 \(G\) 的一个搜索树 \(S\) 以及 \(S\) 的一个 DFS 序,并对 DAG 上的每个点预处理出该点可以到达的所有点的 dfn 值构成的连续区间的集合

查询时通过二分判断是否存在一个区间包含 \(\mathrm{dfn}(b)\),做到 \(\mathcal O(\log \sigma(a))\),其中 \(\sigma(a)\) 为连续段数。

3.2 具体做法

设有向无环图(DAG)

\[G=(V,E) \]

并令 \(x\in V\)。记顶点的出度为

\[\deg^+(v):=|\{w\in V\mid (v,w)\in E\}|. \]

定义从 \(x\) 出发的路径集(允许长度 \(0\) 的空路径):

\[\mathcal P_x:=\{p=(v_0,v_1,\dots,v_k)\mid v_0=x\land k\ge 0\land\forall i:\ (v_i,v_{i+1})\in E\}. \]

对路径 \(p=(v_0,\dots,v_k)\) 定义其终点 \(\mathrm{end}(p):=v_k\),则按路径计数的出度之和记为:

\[S_{\mathrm{mult}}(x):=\sum_{p\in\mathcal P_x}\deg^+\bigl(\mathrm{end}(p)\bigr) \]

在有限的 DAG 上 \(\mathcal P_x\) 有限,因此上式是有限和。

\(G\) 进行一次深度优先搜索,对于每个点 \(x\) 连到的点 \(\{y\mid(x,y)\in E\}\),按 \(S_{\mathrm{mult}}(y)\) 从大到小依次尝试访问,得到一个 DFS 序。然后暴力预处理每个点可以到达的所有点的 dfn 值构成的连续区间的集合

查询直接二分然后判一下。

3.3 参考代码

#include<bits/stdc++.h>
#define ll long long
#define mxn 200003
#define md 1000000007
#define pb push_back
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rept(i,a,b) for(int i=(a);i<(b);++i)
#define drep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
inline int read(){int x=0;bool flag=true;char ch=getchar();while(!isdigit(ch)){if(ch=='-')flag=false;ch=getchar();}while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();return flag?x:-x;
}
struct node{int l,r;
}st[mxn*200];
int n,m,q,tot,c[mxn],rt[mxn],dfn[mxn],a[205][205];
vector<int>g[mxn],e[mxn];
vector<node>s[mxn];
bool v[mxn];
ll sz[mxn];
void dfs(int x){dfn[x]=++tot,v[x]=1;sort(g[x].begin(),g[x].end(),[](int x,int y){return sz[x]>sz[y];});for(int i:g[x])if(!v[i]){e[x].pb(i);dfs(i);}rt[x]=tot;
}
inline void add(int x,int y){g[x].pb(y),c[y]++;
}
void build(){n=read(),m=read();for(int i=0,x,y;i<m;++i){x=read(),y=read();add(x,y);}
}
signed main(){build();rep(i,1,n){if(!c[i])g[0].pb(i);sz[i]=g[i].size();}drep(i,n,1){for(int j:g[i])sz[i]+=sz[j];}tot=-1;dfs(0);tot=0;ll mx=0,sum=0;drep(i,n,1){st[tot=1]={dfn[i],rt[i]};for(int j:g[i])for(node k:s[j])st[++tot]=k;sort(st+1,st+tot+1,[](node x,node y){return x.l==y.l?x.r>y.r:x.l<y.l;});rep(j,1,tot){if(s[i].empty())s[i].pb(st[j]);else if(st[j].l>s[i][s[i].size()-1].r+1)s[i].pb(st[j]);else s[i][s[i].size()-1].r=max(s[i][s[i].size()-1].r,st[j].r);}mx=max(mx,(ll)s[i].size());sum+=s[i].size();}cerr<<mx<<" "<<(double)sum/n<<'\n';q=read();int x,y;while(q--){x=read(),y=dfn[read()];int l=0,r=s[x].size()-1;while(l<r){int mid=(l+r)>>1;if(s[x][mid].l<=y)r=mid;else l=mid+1;}puts(s[x][l].r>=y&&s[x][l].l<=y?"Yes":"No");}return 0;
}

4. 对于各类图的复杂度分析

咕咕咕

4.1 一种随机图:

考虑通过以下方式建图:

void build(){mt19937 mt((unsigned ll)new char);n=1e4,m=2e5;rep(i,1,m){int x=mt()%n+1,y=mt()%n+1;while(x==y)x=mt()%n+1,y=mt()%n+1;if(x>y)swap(x,y);add(x,y);}
}

输出数据:203 115.135

m=1e5353 175.38

n=1e5,m=2e571 6.5275

运行时间较短。

4.2 在随机树上随机撒边:

考虑通过以下方式建图:

void build(){mt19937 mt((unsigned ll)new char);n=1e5,m=2e5;rept(i,1,n){add(mt()%i+1,i+1);}rep(i,1,m-n+1){int x=mt()%n+1,y=mt()%n+1;while(x==y)x=mt()%n+1,y=mt()%n+1;if(x>y)swap(x,y);add(x,y);}
}

输出数据:11342 20.3504

运行时间较短。

4.3 在菊花图/链上随机撒边:

考虑通过以下两种方式建图:

void build(){mt19937 mt((unsigned ll)new char);n=1e5,m=2e5;rept(i,1,n){add(1,i+1);}rep(i,1,m-n+1){int x=mt()%n+1,y=mt()%n+1;while(x==y)x=mt()%n+1,y=mt()%n+1;if(x>y)swap(x,y);add(x,y);}
}
void build(){mt19937 mt((unsigned ll)new char);n=1e5,m=2e5;rept(i,1,n){add(i,i+1);}rep(i,1,m-n+1){int x=mt()%n+1,y=mt()%n+1;while(x==y)x=mt()%n+1,y=mt()%n+1;if(x>y)swap(x,y);add(x,y);}
}

输出数据分别为:9 1.7415611 5.24551,运行时间较短。

5. Hack

忘了,咕咕咕。

6. 拓展

该算法将可达点转化为若干区间,容易处理一些更复杂的问题。

6.1 可达点权值之和

处理出可达点区间,容易通过处理前缀和快速查询。

用一些类似根号分治的东西可以将权值动态化。

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

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

相关文章

网络空间威慑:通过“曝光”手段反制国家级网络间谍活动

在本期“两个极客”节目中,安全研究员The Grugq与政策情报专家Tom Uren深入探讨了是否可能通过“人肉搜索”等干扰措施来威慑国家行为体,使其停止网络间谍活动。内容涉及对特定黑客组织如“迷人小猫”的曝光案例分析…

Gemini 2.5原生音频技术与多模态能力解析

本文详细介绍了Gemini 2.5在音频对话与生成方面的原生技术能力,涵盖实时对话、可控文本转语音、多语言支持以及安全部署等核心技术架构与应用实现。Gemini 2.5的原生音频能力 Gemini自设计之初便是多模态的,原生理解…

实用指南:多种时间序列预测算法的MATLAB实现

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

[开源项目] 蜜蜂记账 v2.2 发布:暗黑模式、标签系统、预算管理等 10+ 新功能

项目介绍 蜜蜂记账(BeeCount)是一款开源的跨平台记账应用,使用 Flutter 开发,支持 iOS 和 Android。 项目最大的特点是数据自主可控:支持 iCloud、Supabase、WebDAV、S3 协议等多种云同步方案,用户可以将数据存储…

12 月记录

QOJ14945 QOJ14949 QOJ14711 QOJ14718 QOJ2064 CF2161F QOJ14685 QOJ14025 QOJ14419 https://atcoder.jp/contests/fps-24/tasks/fps_24_r QOJ14426 QOJ5039 P11983 [JOIST 2025] 展览会 3 / Exhibition 3 P13740 [NWE…

嵌入式软件架构--多窗口表明1(后台软件实现)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

【09】Word文档处理工具

【09】Word文档处理工具 原理图文档处理工具 原理图库文档处理工具 PCB文档处理工具 PCB库文档处理工具 [0901]Word文档批量转换成PDF.rar 下载链接 [0902]Word文档批量转换成TXT.rar 下载链接

谁在主导“芯片战争”

“芯片,不只是电子元件,更是国家角力的新战场。” 过去三年,全球半导体产业如同棋盘上疾速变动的局面:美国推动芯片立法、拔高工具出口壁垒;台湾、韩国厂商扩张制造版图;中国则在稀土、设备供应链端反击。参与者…

定制化 Live555 实战:按需开发低耗 RTSP 服务器,完美适配 C# 项目 - 源之缘

深耕 Live555 源码核心,具备成熟定制化开发能力,可按需打造高性能 RTSP 服务器。封装的极简 C 接口,4 步即可完成部署,C#/.NET 可无缝集成,大幅降低开发门槛。底层复用 Live555 事件驱动架构,两路高清流并发 CPU…

KEIL5软件查看函数最大调用深度12.7

KEIL5软件查看函数最大调用深度12.7在option设置Linker页面,添加--info stack再重新编译后就可以在Map文件中查看到函数调用深度这个好像没什么关系,开不开都可以看到

2025深圳CNC加工实力榜:金丰业五金塑胶以精密智造领跑,六家本土技术标杆企业核心优势深度解析

2025深圳CNC加工实力榜:金丰业五金塑胶以精密智造领跑,六家本土技术标杆企业核心优势深度解析 在制造业向高端化、智能化转型的浪潮中,CNC(计算机数控)加工技术已成为衡量一个地区乃至一个国家先进制造能力的核心…

Day13-20251207

本文介绍了Java编程中的包机制和JavaDoc文档生成方法。包机制通过域名倒置命名规范组织类文件,使用package和import语句管理命名空间。JavaDoc用于生成API文档,支持@author、@version等参数标注,可通过命令行工具生…

一些复数的有趣的恒等式

1 \[|z_1 + z_2|^2 + |z_1 - z_2|^2 = 2(|z_1|^2 + |z_2|^2|) \]2 \[|\alpha - \beta|^2 = |\alpha|^2 + |\beta|^2 - 2\text{Re}(\overline{\alpha}\beta) = |\alpha|^2 + |\beta|^2 - 2\text{Re}(\alpha\overline{\b…

DeepSeek-OCR 模型的下载

前提,安装命令行工具 huggingface-cli 或者 hf 或 modelscope 或 aistudio 等命令行工具以及 git. HF_ENDPOINT=https://hf-mirror.com hf download deepseek-ai/DeepSeek-OCR --cache-dir ~/.cache/huggingface/hu…

C# 与 .NET 跨平台制作实战(第一章:开发环境搭建与.NET概述-上篇)

C# 与 .NET 跨平台制作实战(第一章:开发环境搭建与.NET概述-上篇)2025-12-07 18:46 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto …

2025散热风扇厂家实力排行榜:万航电子以智能温控技术领跑,六家高潜力本土品牌深度解析

2025散热风扇厂家实力排行榜:万航电子以智能温控技术领跑,六家高潜力本土品牌深度解析 在工业自动化、数据中心、消费电子及新能源等产业高速发展的驱动下,散热风扇作为保障设备稳定运行的核心部件,其技术迭代与市…

AI 清洁管理系统:响应 3 秒,人力成本降低 42%

餐厅大厅本该是味蕾与氛围的交响,却常被垃圾满溢、地面油渍、灯光闪烁破坏:垃圾桶溢出酸腐味,顾客皱眉离席;地面湿滑无人知,高峰翻台卡壳;灯闪如迪厅,安全+体验双崩——2025年,餐饮环境投诉占总差评48%,平均每…

2025东莞力利机械压铸设备实力榜:六家国产技术代表企业,热室与冷室压铸机核心优势深度解析

2025东莞力利机械压铸设备实力榜:六家国产技术代表企业,热室与冷室压铸机核心优势深度解析 在全球制造业持续升级与精密化转型的浪潮下,压铸技术作为现代工业,尤其是汽车、电子、通信及高端五金领域不可或缺的成型…

岐金兰意义行为原生理论与AI元人文价值操作系统研究

岐金兰"意义行为原生"理论与AI元人文价值操作系统研究 一、引言:从"价值对齐"困境到"意义行为原生"的范式革命 1.1 传统"价值对齐"范式的深层困境 人工智能技术的纵深发展已…

virtualbox+ubuntu+vscode+ssh pwn环境配置

额话说一直想弄一个ubuntu环境,但是硬盘没容量,最近下狠心加了一个固态1T的移动硬盘,然后就有机会部署一个完整的环境了。 感觉之前都是用虚拟机的GUI很卡,所以说想到了VSCODE+SSH(说实话我很少用VSCODE,虽然装了…