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; 
      }
    }
  }


posted @ 2022-09-20 15:33  雪之下,树之旁  阅读(69)  评论(0编辑  收藏  举报