可达性统计(拓扑排序)

Posted 1625--h

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可达性统计(拓扑排序)相关的知识,希望对你有一定的参考价值。

描述

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

输入格式

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

输出格式

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

样例输入

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

分析:拓扑排序,为了计数方便避免重复记录后续,使用bitset来储存n个结点对于n个结点的可达情况,二进制直接通过或运算即可从后向前扫描拓扑序列。

#define MAX 30001
int head[MAX],nxt[MAX],ver[MAX],deg[MAX];
int a[MAX];
int n,m;
int cnt = 0,tot=0;
bitset<30001> s[MAX];
void add(int x,int y)
{
    ver[++tot] = y;
    nxt[tot] = head[x];
    head[x] = tot;
    deg[y]++;
}
void topsort()
{
    queue<int>q;
    for(int i= 1;i<=n;i++)
        if(deg[i]==0)
            q.push(i);
    while(q.size())
    {
        int x = q.front();
        q.pop();
        a[++cnt] = x;
        for(int i=head[x];i;i=nxt[i])
        {
            int y = ver[i];
            if(--deg[y]==0)
                q.push(y);
        }
    }
}
void sol()
{
    for(int i=cnt;i;i--)
    {
        int x = a[i];
        s[x][x] = 1;
        for(int j=head[x];j;j=nxt[j])
        {
            int y=ver[j];
            s[x]|=s[y];
        }
    }
}
int main() 
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
    }
    topsort();
    sol();
    for(int i=1;i<=n;i++)
    {
        printf("%d
",s[i].count());
    }
    return 0;
}

以上是关于可达性统计(拓扑排序)的主要内容,如果未能解决你的问题,请参考以下文章

可达性统计(拓扑排序)

AcWing 164. 可达性统计(拓扑排序+bitset优化)

AcWing 164.可达性统计(图论+拓扑排序+位运算)

AcWing 164.可达性统计(图论+拓扑排序+位运算)

AcWing 164.可达性统计(图论+拓扑排序+位运算)

AcWing 164.可达性统计(图论+拓扑排序+位运算)