可达性统计

给定一张 NN 个点 MM 条边的有向无环图,分别统计从每个点出发能够到达的点的数量。

输入格式

第一行两个整数 N,MN,M,接下来 MM 行每行两个整数 x,yx,y,表示从 xx 到 yy 的一条有向边。

输出格式

输出共 NN 行,表示每个点能够到达的点的数量。

数据范围

1N,M300001≤N,M≤30000

输入样例:

10 10
3 8
2 3
2 5
5 9
5 9
2 3
3 9
4 8
2 10
4 9

输出样例:

1
6
3
3
2
1
1
1
1
1
#include<bits/stdc++.h>

using namespace std;

const int N = 3e4+10;
int h[N], e[N], ne[N], idx;
bitset<N> f[N];
int d[N], ni[N];
int n, m;

void add(int a, int b)
{
    e[++idx] = b;
    ne[idx] = h[a];
    h[a] = idx;
}

void topsort()
{
    queue<int> q;

    for(int i = 1; i <= n; i++)
        if(!d[i]) q.push(i);

    int k = 0;
    while(q.size())
    {
        int t = q.front();
        q.pop();
        ni[++k] = t;
        for(int i = h[t]; ~i; i = ne[i])
        {
            if(--d[e[i]] == 0) q.push(e[i]);
        }
    }
}
int main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);

    for(int i = 1; i <= m; i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b);
        d[b]++;
    }

    topsort();
    
    for(int i = n; i >= 1; i --)
    {
        int j = ni[i];
        f[j][j] = 1;
        for(int k = h[j]; ~k; k = ne[k])
        {
            f[j] |= f[e[k]];
        }
    }

    for(int i = 1; i <= n; i++)
    {
        cout << f[i].count() << endl;
    }
    
    
    return 0;
}

 

posted @ 2022-09-15 17:04  Luli&  阅读(37)  评论(0)    收藏  举报