B3611 【模板】传递闭包-普及/提高-
B3611 【模板】传递闭包
题目描述
给定一张点数为 nnn 的有向图的邻接矩阵,图中不包含自环,求该有向图的传递闭包。
一张图的邻接矩阵定义为一个 n×nn\times nn×n 的矩阵 A=(aij)n×nA=(a_{ij})_{n\times n}A=(aij)n×n,其中
aij={1,i 到 j 存在直接连边0,i 到 j 没有直接连边 a_{ij}=\left\{ \begin{aligned} 1,i\ 到\ j\ 存在直接连边\\ 0,i\ 到\ j\ 没有直接连边 \\ \end{aligned} \right. aij={1,i 到 j 存在直接连边0,i 到 j 没有直接连边
一张图的传递闭包定义为一个 n×nn\times nn×n 的矩阵 B=(bij)n×nB=(b_{ij})_{n\times n}B=(bij)n×n,其中
bij={1,i 可以直接或间接到达 j0,i 无法直接或间接到达 j b_{ij}=\left\{ \begin{aligned} 1,i\ 可以直接或间接到达\ j\\ 0,i\ 无法直接或间接到达\ j\\ \end{aligned} \right. bij={1,i 可以直接或间接到达 j0,i 无法直接或间接到达 j
输入格式
输入数据共 n+1n+1n+1 行。
第一行一个正整数 nnn。
第 222 到 n+1n+1n+1 行每行 nnn 个整数,第 i+1i+1i+1 行第 jjj 列的整数为 aija_{ij}aij。
输出格式
输出数据共 nnn 行。
第 111 到 nnn 行每行 nnn 个整数,第 iii 行第 jjj 列的整数为 bijb_{ij}bij。
输入输出样例 #1
输入 #1
4
0 0 0 1
1 0 0 0
0 0 0 1
0 1 0 0
输出 #1
1 1 0 1
1 1 0 1
1 1 0 1
1 1 0 1
说明/提示
对于 100%100\%100% 的数据,1≤n≤1001\le n\le 1001≤n≤100,保证 aij∈{0,1}a_{ij}\in\{0,1\}aij∈{0,1} 且 aii=0a_{ii}=0aii=0。
solution
Ford 算法可以认为是一种动态规划,设 d[k][i][j] 为如果用前 k 个点松弛的话,i,j的最短路径,d[k][i][j] = min(d[k-1][i][k] + d[k-1][k][j]) 但是存储时可以省略一个维度 d[i][j] = min(d[i][k] + d[k][j])即可,三层循环。复杂度 O(n^3)
代码
#include <iostream>
#include "bit"
#include "vector"
#include "unordered_set"
#include "unordered_map"
#include "set"
#include "queue"
#include "algorithm"
#include "bitset"
#include "cstring"
#include "cmath"using namespace std;typedef long long ll;
const int N = 1e5 + 5, inf = 1e9 + 1;int n, f[105][105];int main() {cin >> n;for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)cin >> f[i][j];for (int k = 1; k <= n; k++)for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)if (f[i][k] && f[k][j]) f[i][j] = 1;for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++)cout << f[i][j] << ' ';cout << endl;}return 0;
}