AcWing 164. 可达性统计
新掌握一个容器bitsetS,这个二进制数S的长度为N,可以储存N位二进制数。可以说是一个多位二进制数,每八位占用一个字节,因为支持基本的位运算,所以可用于状态压缩,n位bitset执行一次位运算的时间复杂度可视为n/32.
用二进制的1表示可达到的点,先进行拓扑排序,之后按拓扑排序的逆序进行dp,进行或运算,f[i]储存的是点i能到达那些点,每个1都表示一个点
#include<bits/stdc++.h>
using namespace std;
const int N = 31000, M = 62000;
int h[N], e[M], ne[M], idx;
bitset<N>f[N]; //记录N个二进制数
int n, m;
int din[N];
int q[N];
void add(int a, int b){
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++ ;
}
void topsort(){
int hh = 0, tt = -1;
for(int i = 1; i <= n; i ++ ){
if(!din[i]){
q[ ++ tt] = i;
}
}
while(hh <= tt){
int t = q[hh ++ ];
for(int i = h[t]; ~i; i = ne[i]){
int j = e[i];
if( -- din[j] == 0) q[ ++ tt] = j;
}
}
}
int main()
{
cin>>n>>m;
memset(h, -1, sizeof h);
while(m -- ){
int a, b;
cin>>a>>b;
add(a, b);
din[b] ++ ;
}
topsort();
for(int i = n - 1; i >= 0; i -- ){
int j = q[i];
f[j][j] = 1;
for(int k = h[j]; ~k; k = ne[k]){
int u = e[k];
f[j] |= f[u];
}
}
for(int i = 1; i <= n; i ++ ) cout<<f[i].count()<<endl;
return 0;
}