Floyd传递闭包讲解
传递闭包概念很简单: 对于图内三点 \(i, j, k\) 如果 \(i -> j\) 可以, \(j -> k\) 可以,那么 \(i -> k\) 也可以。
那么用 \(Floyd\) 就很好实现了, 三重循环 \(i, j, k\) 即可。
同时,在这里可以使用 $ bitset $ 优化,尤其是对于这种只有 \(0\) 或 \(1\) 两种状态的需求。
bitset <N> f[N]; /*用bitset时,f[i][j] = 1(即第j位) 代表从 i -> j 可行。这里通过“或运算省去了对 k 的枚举”*/
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){ // 合并
if(f[j][i])
f[j] |= f[i];
}
}
/* 普通写法:
多一层循环 k, 若 i -> k 可以,j -> i 可以, 则 j -> k 可以
*/
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){ // 合并
for(int k = 1; k <= n; k++){
if(f[j][i] && f[i][k])
f[j][k] = 1;
}
}
}