zoukankan      html  css  js  c++  java
  • AcWing 164. 可达性统计

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

    输入格式

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

    输出格式

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

    数据范围

    1N,M30000


    显然可以用拓扑排序+状态压缩来做, 用一个n位的二进制数存每一个f[x], 其中第i位是1表示x能到i,0则不能到i, 这样就相当于存在x 到 y的一条边,f[x] |= f[y], 再预处理处拓扑序, 反向枚举, 最后判断每个f[i]中的个数, 但有一个bug就是, 就算unsigned long long 二进制下只有64位, 这里就有一个小小的干货:

    关于状态压缩 bitset容器:
    转载:https://oi-wiki.org/ds/stl/bitset/
    介绍¶
    std :: bitset 是标准库中的一个固定大小序列,其储存的数据只包含 0/1

    众所周知,由于内存地址是按字节即 byte 寻址,而非比特 bit ,

    我们一个 bool 类型的变量,虽然只能表示 0/1 , 但是也占了 1byte 的内存

    bitset 就是通过固定的优化,使得一个字节的八个比特能分别储存 8 位的 0/1

    对于一个 4 字节的 int 变量,在只存 0/1 的意义下, bitset 占用空间只是其

    在某些情况下通过 bitset 可以使你的复杂度除以 32

    当然, vector 的一个特化 vector<bool> 的储存方式同 bitset 一样,区别在于其支持动态开空间,

    bitset 则和我们一般的静态数组一样,是在编译时就开好了的。

    那么为什么要用 bitset 而非 vector<bool> ?

    通过以下的介绍,你可以更加详细的看到 bitset 具备的方便操作

    #include <bitset> // 包含 bitset 的头文件
    运算符¶
    operator[] : 访问其特定的一位

    operator ==/!= : 比较两个 bitset 内容是否完全一样

    operator &=/|=/^=/~ : 进行按位与/或/异或/取反操作

    operator <</>>/<<=/>>= : 进行二进制左移/右移

    operator <</>> : 流运算符,这意味着你可以通过 cin/cout 进行输入输出

    vector<bool> 只具有前两项

    成员函数¶
    test() : 它和 vector 中的 at() 的作用是一样的,和 [] 运算符的区别就是越界检查
    count() : 返回 true 的数量
    set() : 将整个 bitset 设置成 true , 你也可以传入参数使其设置成你的参数
    reset() : 将整个 bitset 设置成 false
    flip() : 翻转该位 (0 变 1,1 变 0), 相当于逻辑非/异或 1
    to_string() : 返回转换成的字符串表达
    to_ulong() : 返回转换成的 unsigned long 表达 ( long 在 NT 及 32 位 POSIX 系统下与 int 一样,在 64 位 POSIX 下与 long long 一样)
    to_ullong() C++11, 返回转换成的 unsigned long long 表达
    这些 vector<bool> 基本都没有

    作用¶
    一般来讲,我们可以用 bitset 优化一些可行性 DP, 或者线筛素数 ( notprime 这种 bool 数组可以用 bitset 开到 之类的)

    它最主要的作用还是压掉了内存带来的时间优化, 的常数优化已经可以是复杂度级别的优化了,比如一个 的 算法, 显然很卡,在常数大一点的情况下必然卡不过去,O(松)不能算!, 这时候如果我们某一维除以 32, 则可以比较保险的过了这道题

    其实 bitset 不光是一个容器,更是一种思想,我们可以通过手写的方式,来把 long long 什么的压成每 bit 表示一个信息,用 STL 的原因更多是因为它的运算符方便

    作者:Chicago
    链接:https://www.acwing.com/solution/acwing/content/899/
    来源:AcWing

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    const int INF = 0x3f3f3f3f;
    const int MAXN = 3e4 + 100;
    const int MAXM = 3e3 + 10;
    const double eps = 1e-5;
    
    template < typename T > inline void read(T &x) {
        x = 0; T ff = 1, ch = getchar();
        while(!isdigit(ch)) {
            if(ch == '-') ff = -1;
            ch = getchar();
        }
        while(isdigit(ch)) {
            x = (x << 1) + (x << 3) + (ch ^ 48);
            ch = getchar(); 
        }
        x *= ff;
    }
    
    
    template < typename T > inline void write(T x) {
        if(x < 0) putchar('-'), x = -x;
        if(x > 9) write(x / 10);
        putchar(x % 10 + '0');
    }
    
    int n, m, top, in[MAXN], b[MAXN];
    bitset < MAXN > a[MAXN];
    int lin[MAXN], tot = 0;
    struct edge {
        int y, next;
    }e[MAXN];
    
    inline void add(int xx, int yy) {
        e[++tot].y = yy;
        e[tot].next = lin[xx];
        lin[xx] = tot;
    }
    
    void topsort() {
        queue < int > q;
        for(int i = 1; i <= n; ++i) {
            if(in[i] == 0) q.push(i);
        } 
        while(!q.empty()) {
            int x = q.front(); q.pop();
            b[++top] = x;
            for(int i = lin[x], y; i; i = e[i].next) {
                if(--in[y = e[i].y] == 0) q.push(y);                                                        
            } 
        }
        
    }
    
    int main() {
        read(n); read(m);
        for(int i = 1; i <= m; ++i) {
            int x, y;
            read(x); read(y);
            add(x, y);
            in[y]++;
        } 
        topsort();
        for(int i = top; i >= 1; --i) {
            int x = b[i];
            a[x][x] = 1;
            for(int j = lin[x]; j; j = e[j].next) {
                a[x] |= a[e[j].y]; 
            }
        } 
        for(int i = 1; i <= n; ++i) {
            cout << a[i].count() << endl;
        }
        
        return 0;
    }
  • 相关阅读:
    单例模式
    自旋锁与互斥锁
    CAS无锁机制原理
    乐观锁和悲观锁
    读写锁
    Java锁机制-重入锁
    原 Linux搭建SVN 服务器2
    原 Linux搭建SVN 服务器
    Sublime Text 3 破解版 + 注册机 + 汉化包 + 教程
    Sublime Text 3 常用插件以及安装方法(转)
  • 原文地址:https://www.cnblogs.com/AK-ls/p/11106434.html
Copyright © 2011-2022 走看看