这是在学 2 − S A T 2-SAT 2−SAT 的时候突然看到的一个东西,就顺便学了一下。
先了解一下传递闭包的定义,来一张网上广泛用到的图:
说白了就是
c
[
i
]
[
j
]
c[i][j]
c[i][j] 表示
i
i
i 能不能到
j
j
j,能为
1
1
1,不能为
0
0
0。
显然可以用 f l o y d floyd floyd 来求这个东西,时间复杂度为 O ( n 3 ) O(n^3) O(n3)。
由于这个东西只需要记录 0 / 1 0/1 0/1,所以可以用 b i t s e t bitset bitset 来优化,原本一个 b o o l bool bool 占用一个 b y t e byte byte,而 b i t s e t bitset bitset 里面的一位只占用一个 b i t bit bit,不仅时间乘上了一个常数 1 64 \frac 1 {64} 641,空间也节省了。
题目大意: 给出 m m m 组大小关系,问将这 n n n 个元素进行排序还需要几组大小关系。
代码如下:
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
#define maxn 1010
int n,m,ans=0;
bitset<maxn>f[maxn];
int main()
{
scanf("%d %d",&n,&m);
for(int i=1,x,y;i<=m;i++)
scanf("%d %d",&x,&y),f[x][y]=1;
for(int i=1;i<=n;i++)//floyd
for(int j=1;j<=n;j++)if(i!=j)
if(f[j][i])f[j]|=f[i];
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(!f[i][j]&&!f[j][i])ans++;
printf("%d",ans);
}