• CH2101:【可达性统计】(拓扑排序+状态压缩)


    设从点 x 出发能够到达的点构成的集合是 f(x),从点 x 出发能够到达的点,是从 x 的各个后继节点 y 出发能够到达的点的并集,再加上点 x 自身 。

    比如从2出发可以到达点5 8 9,则f(2)=f(5)Uf(8)Uf(9)

    先按照拓扑排序算法求出拓扑序,然后按照拓扑序的倒序进行计算------因为在拓扑序中,任意一条边 (x , y),x 都排在 y 之前。

    我们可以用一个N位2进制数来表示每个f(x),二进制数的第i位为1表示x可以到达点i,二进制中1的个数就是这个点可以到达的点的数目,这样一来,对若干个集合求并集,就是对若干个N位二进制数做按位或

    用bitset存储f(x)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 3e4 + 10;
    vector<int>edge[maxn], ans;
    queue<int> que;
    bitset<maxn> b[maxn];
    int in[maxn], n, m,x,y;
    void topo_sort()
    {
        for (int i = 1; i <= n;i++)
            if (!in[i]) que.push(i);
        while (!que.empty())
        {
            int v = que.front();
            que.pop();
            ans.push_back(v);
            for (int i = 0; i < edge[v].size(); i++)
            {
                if (--in[edge[v][i]] == 0) 
                    que.push(edge[v][i]);
            }
        }
    }
    void solve()
    {
        topo_sort();
        for (int i = ans.size() - 1; i>=0; i--)
        {
            int v = ans[i];
            //b[v].reset();
            b[v][v] = 1;
            for (int j = 0; j < edge[v].size(); j++)
            {
                b[v] |= b[edge[v][j]];
            }
        }
        for (int i = 1; i <= n; i++)
            cout << b[i].count() << endl;
    }
    int main()
    {
        cin >> n >> m;
        for (int i = 1; i <= m; i++)
        {
            cin >> x >> y;
            edge[x].push_back(y);
            in[y]++;
        }
        solve();
        return 0;
    }
  • 相关阅读:
    webpack-dev-server的使用及说明
    Web框架
    HTTP协议
    jQuery的使用
    发红包
    python操作mysql
    mysql索引与补充
    JavaScript之BOM操作
    JavaScript之DOM操作
    JavaScript之基础语法
  • 原文地址:https://www.cnblogs.com/xiaoguapi/p/10383319.html
Copyright © 2020-2023  润新知