本文属于「算法学习」系列文章之一。之前的【数据结构和算法设计】系列着重于基础的数据结构和算法设计课程的学习,与之不同的是,这一系列主要用来记录对大学课程范围之外的高级算法学习、优化与使用的过程,同时也将归纳总结出简洁明了的算法模板,以便记忆和运用。在本系列学习文章中,为了透彻讲解算法和代码,本人参考了诸多博客、教程、文档、书籍等资料,由于精力有限,恕不能一一列出。
为了方便在PC上运行调试、分享代码,我还建立了相关的仓库:https://github.com/memcpy0/Algorithm-Templates。在这一仓库中,你可以看到算法文章、模板代码、应用题目等等。由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏算法学习系列文章目录一文以作备忘。
1. 传递闭包含义和实现
在离散数学的图论专题中,一般都会学到「传递闭包」这种算法。从集合论角度来看,传递闭包是在集合 X X X 上求包含二元关系 R R R 的最小传递关系;从图论角度来看,如果原关系图上有 u u u 到 v v v 的路径,则传递闭包的关系图上就有从 u u u 到 v v v 的边——实际上就是确定每个点是否能够到达其他每个点。
具体来说,修改一下全源最短路Floyd算法即可。依次判断:仅经过顶点 1
能不能从 i
到达 j
,仅经过顶点 1, 2
能不能从 i
到达 j
……,仅经过顶点 1, 2, ..., n
能不能从 i
到达 j
,能够到达则赋值为 1
,表示 i
可达 j
。设 M
为关系图的关系矩阵,求其传递闭包的具体代码如下,时间复杂度为
O
(
n
3
)
O(n^3)
O(n3) :
for (int k = 1; k <= n; ++k)
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
if (M[i][k] && M[k][j])
M[i][j] = 1;
或者说,使用Floyd-Warshall算法——就是上述代码的变形:
for (int k = 1; k <= n; ++k)
for (int i = 1; i <= n; ++i)
if (M[i][k])
for (int j = 1; j <= n; ++j)
M[i][j] = M[i][j] || M[k][j];
2. 各大OJ题目应用
题目链接 | 题解文章 |
---|---|
POJ 1975 Median Weight Bead | POJ 1975 Median Weight Bead【传递闭包】 |
POJ 3660 Cow Contest | POJ 3660 Cow Contest【传递闭包】 |