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;
}
posted @ 2021-06-05 22:32  acmloser  阅读(37)  评论(0编辑  收藏  举报