《B3611 【模板】传递闭包》
题目描述
给定一张点数为 n 的有向图的邻接矩阵,图中不包含自环,求该有向图的传递闭包。
一张图的邻接矩阵定义为一个 n×n 的矩阵 A=(aij)n×n,其中
aij={1,i 到 j 存在直接连边0,i 到 j 没有直接连边
一张图的传递闭包定义为一个 n×n 的矩阵 B=(bij)n×n,其中
bij={1,i 可以直接或间接到达 j0,i 无法直接或间接到达 j
输入格式
输入数据共 n+1 行。
第一行一个正整数 n。
第 2 到 n+1 行每行 n 个整数,第 i+1 行第 j 列的整数为 aij。
输出格式
输出数据共 n 行。
第 1 到 n 行每行 n 个整数,第 i 行第 j 列的整数为 bij。
输入输出样例
输入 #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% 的数据,1≤n≤100,保证 aij∈{0,1} 且 aii=0。
代码实现:
#include<cstdio>
// 快速输入函数
inline int input();
// 快速输出函数
inline void output(int num);
// 最大节点数量
const int MAX_NODE = (int)1e2 + 5;
// 邻接矩阵,用于存储传递闭包
int graph[MAX_NODE][MAX_NODE];
int main(int argc, char**argv) {
#ifndef ONLINE_JUDGE
// 本地调试时的文件输入输出
freopen("7909.in", "r", stdin);
freopen("7909.out", "w", stdout);
#endif
// 读取节点数量
register int nodeCount = input();
// 读取邻接矩阵
for (register int i = 1; i <= nodeCount; ++i) {
for (register int j = 1; j <= nodeCount; ++j) {
graph[i][j] = input();
}
}
// Floyd-Warshall算法计算传递闭包
// 通过中间节点midNode更新可达性
for (register int midNode = 1; midNode <= nodeCount; ++midNode) {
for (register int startNode = 1; startNode <= nodeCount; ++startNode) {
for (register int endNode = 1; endNode <= nodeCount; ++endNode) {
// 如果startNode可达midNode且midNode可达endNode,则startNode可达endNode
if (graph[startNode][midNode] && graph[midNode][endNode]) {
graph[startNode][endNode] = 1;
}
}
}
}
// 输出传递闭包矩阵
for (register int i = 1; i <= nodeCount; ++i, putchar('\n')) {
for (register int j = 1; j <= nodeCount; ++j) {
output(graph[i][j]);
putchar(' ');
}
}
return 0;
}
// 快速输入实现
inline int input() {
register char ch = getchar();
register int value = 0;
register int sign = 1;
// 处理符号
for (; ch < '0' || ch > '9'; ch = getchar()) {
if (ch == '-') {
sign = -1;
}
}
// 处理数字
for (; ch >= '0' && ch <= '9'; ch = getchar()) {
value = (value << 1) + (value << 3) + (ch & 15);
}
return value * sign;
}
// 快速输出实现
inline void output(int num) {
if (num < 0) {
putchar('-');
num = -num;
}
if (num / 10) {
output(num / 10);
}
putchar(num % 10 + '0');
}