Files
Data-Structure/模板//Floyd闭包传递.cpp
2025-12-16 20:36:27 +08:00

79 lines
1.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
#include <vector>
using namespace std;
/*
* Floyd-Warshall 传递闭包Transitive Closure
* ----------------------------------------------
* 用途:求有向图中任意两点 i -> j 是否可达。
*
* 核心思想:
* 如果 i 能到达 k 且 k 能到达 j
* 则 i 也能到达 j
*
* reach[i][j] = reach[i][j] || (reach[i][k] && reach[k][j])
*
* 输入:
* n节点数量默认节点编号为 0~n-1
* m边数量
* 若干有向边 u -> v
*
* 结果:
* reach[i][j] = true 表示可达
*/
int main() {
int n, m;
cin >> n >> m;
// reach[i][j] 表示 i 是否能到 j
vector<vector<bool>> reach(n, vector<bool>(n, false));
// 自身可达
for (int i = 0; i < n; i++) {
reach[i][i] = true;
}
// 输入边
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
reach[u][v] = true;
}
/*
* Floyd 传递闭包核心循环
* i -> k -> j 中的 k 作为中间点
*
* 需要确保三重循环的顺序为:
* for(k)
* for(i)
* for(j)
*
* 必须这么写,因为:
* - k 作为阶段性“允许使用的中间点”
* - 在第 k 轮,只能使用编号 ≤ k 的中间节点
*/
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
// 如果 i → k 不可达,则无须检查 j
if (!reach[i][k]) continue;
for (int j = 0; j < n; j++) {
// 如果 k → j 可达,则 i → j 也可达
if (reach[k][j]) {
reach[i][j] = true;
}
}
}
}
// 输出可达矩阵(可选)
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << reach[i][j] << (j + 1 == n ? '\n' : ' ');
}
}
return 0;
}