• AcWing:164. 可达性统计(拓扑排序 + 状态压缩算法)


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

    输入格式

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

    输出格式

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

    数据范围

    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

    算法:拓扑排序 + 状态压缩算法

    题解:首先求出该有向无环图的拓扑序列,根据拓扑序列的性质:在拓扑序种,对于任意一条边(x, y)来说,x都会排在y之前(读者可以自行画图证明)。然后倒叙遍历拓扑序来结果状态压缩来求的结果。

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <bitset>
    #include <queue>
    
    using namespace std;
    
    const int maxn = 3e4+7;
    
    vector<int> g[maxn];
    vector<int> a;
    bitset<maxn> f[maxn];
    
    int in[maxn];
    int n, m;
    
    void topsort() {
        queue<int> q;
        for(int i = 1; i <= n; i++) {
            if(in[i] == 0) {
                q.push(i);
            }
        }
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            a.push_back(u);     //记录拓扑序列
            int len = g[u].size();
            for(int i = 0; i < len; i++) {
                int v = g[u][i];
                if(--in[v] == 0) {
                    q.push(v);
                }
            }
        }
    }
    
    void sovle() {
        for(int i = a.size() - 1; i >= 0; i--) {
            int u = a[i];
            f[u].reset();   //清空数组
            f[u][u] = 1;    //将当前位置赋1
            int len = g[u].size();
            for(int j = 0; j < len; j++) {
                int v = g[u][j];
                f[u] = f[u] | f[v];     //将经过的点的状态压缩到当前数组中
            }
        }
    }
    
    int main() {
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= m; i++) {
            int u, v;
            scanf("%d %d", &u, &v);
            g[u].push_back(v);
            in[v]++;
        }
        topsort();
        sovle();
        for(int i = 1; i <= n; i++) {
            printf("%d
    ", f[i].count());
        }
        return 0;
    }
  • 相关阅读:
    工厂模式
    Bootstrap 日历
    处理乱码
    Eclipse常用快捷键
    C#_XML与Object转换
    jQuery选择函数
    Bootstrap如何正确引用字体图标
    js上拉加载、下拉刷新的插件
    js通用对象数组冒牌排序
    关于js跨域
  • 原文地址:https://www.cnblogs.com/buhuiflydepig/p/11336314.html
Copyright © 2020-2023  润新知