AcWing 164. 可达性统计
原题链接
考察:拓扑排序
思路:
求拓扑序列,然后从尾到头遍历每个点能到达的点,ans[u] |= ans[子结点1]|ans[子节点2]|ans[子节点3]...
因为需要用到或操作所以考虑位运算,如果每位每位或运算时间复杂度是O(nm),只能用bitset优化,bitset底部用int实现,将n位01串压成n/32位,时间复杂度是O(\(\frac {nm}{32}\))
bitset传送门
Code
#include <iostream>
#include <cstring>
#include <bitset>
using namespace std;
const int N = 30010;
int h[N],idx,d[N],n,m,q[N],ans[N];
bitset<N> foo[N];
struct Road{
int fr,to,ne;
}road[N];
void add(int a,int b)
{
road[idx].fr = a,road[idx].to = b,road[idx].ne = h[a],h[a] = idx++;
}
void topsort()
{
int hh=0,tt=-1;
for(int i=1;i<=n;i++) if(!d[i]) q[++tt] = i;
while(hh<=tt)
{
int u = q[hh++];
for(int i=h[u];~i;i=road[i].ne)
{
int v = road[i].to;
if(--d[v]==0) q[++tt] = v;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(h,-1,sizeof h);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
d[b]++;
}
topsort();
for(int i=n-1;i>=0;i--)
{
int u = q[i];
foo[u].reset();
foo[u].set(u-1,1);
for(int j=h[u];~j;j=road[j].ne)
{
int v = road[j].to;
foo[u]|=foo[v];
}
}
for(int i=1;i<=n;i++) printf("%d\n",foo[i].count());
return 0;
}