zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Python变量、标识符
    PyCharm中设置作者信息
    去中心化
    复杂逻辑---取数
    行政机构处理
    2020.11案例分析
    中间表
    软考--项目管理名词
    软考--近6次上午考点分析
    软考--学习方法、做题方法
  • 原文地址:https://www.cnblogs.com/xiaoguapi/p/10383319.html
Copyright © 2011-2022 走看看