「拓扑排序」可达性统计

Posted nicoppa

tags:

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

可达性统计

原题链接:可达性统计

题目大意

给你一张(n)个点(m)条边的有向无环图,分别统计从每个点出发能够到达的点的数量

题目题解

看到题意就知道要用到拓扑排序,但是拓扑排序的理论复杂度在30000的极限条件下会超时,这个时候我们考虑使用 (bitset),一个很好用的代替bool的防卡常技巧,详细的说明这里不说,可以去百度上查看相关运用

//#define fre yes

#include <queue>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <algorithm>

const int N = 30005;
int head[N << 1], to[N << 1], ver[N << 1];
int in[N], ans[N];

std::bitset<N> f[N];

int tot, k;
void addedge(int x, int y) {
    ver[tot] = y;
    to[tot] = head[x];
    head[x] = tot++;
}

int n, m;

void toposort() {
    std::queue<int> q;
    for (int i = 1; i <= n; i++) {
        if(!in[i]) q.push(i);   
    }
    
    while(!q.empty()) {
        int t = q.front(); q.pop();
        ans[++k] = t;
        for (int i = head[t]; ~i; i = to[i]) {
            int v = ver[i];
            in[v]--;
            if(!in[v]) q.push(v);
        }
    }
}

int main() {
    memset(head, -1, sizeof(head));
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        addedge(u, v);
        in[v] ++;
    } toposort();
    // for (int i = 1; i <= n; i++) {
    //     printf("%d ", ans[i]);
    // }
    
    for (int  i = n; i >= 1; i--) {
        int j = ans[i];
        f[j][j] = 1;
        for (int x = head[j]; ~x; x = to[x]) {
            f[j] |= f[ver[x]];
        }
    }
    
    for (int i = 1; i <= n; i++) {
        printf("%d
", f[i].count());
    } return 0;
}

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

可达性统计(拓扑排序)

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

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

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

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

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