AcWing 164. 可达性统计
給定一張N個點M條邊的有向無環圖,分別統計從每個點出發能夠到達的點的數量。
輸入格式
第一行兩個整數N,M,接下來M行每行兩個整數x,y,表示從x到y的一條有向邊。
輸出格式
輸出共N行,表示每個點能夠到達的點的數量。
數據范圍
1≤N,M≤30000
顯然可以用拓撲排序+狀態壓縮來做, 用一個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
?
轉載于:https://www.cnblogs.com/AK-ls/p/11106434.html
總結
以上是生活随笔為你收集整理的AcWing 164. 可达性统计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自定义MyBatis
- 下一篇: vuex modules 命名空间