AcWing 164 可達性統計

2022-03-29 15:42:45 字數 2795 閱讀 3285

給定一張n個點m條邊的有向無環圖,分別統計從每個點出發能夠到達的點的數量。

輸入格式

第一行兩個整數n,m,接下來m行每行兩個整數x,y,表示從x到y的一條有向邊。

輸出格式

輸出共n行,表示每個點能夠到達的點的數量。

資料範圍1≤

n,m≤

30000

'>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容器:

**:介紹¶std :: bitset 是標準庫中的乙個固定大小序列,其儲存的資料只包含 0/1

眾所周知,由於記憶體位址是按位元組即 byte 定址,而非位元 bit ,

我們乙個 bool 型別的變數,雖然只能表示 0/1 , 但是也佔了 1byte 的記憶體

bitset 就是通過固定的優化,使得乙個位元組的八個位元能分別儲存 8 位的 0/1

對於乙個 4 位元組的 int 變數,在只存 0/1 的意義下, bitset 占用空間只是其

在某些情況下通過 bitset 可以使你的複雜度除以 32

當然, vector 的乙個特化 vector的儲存方式同 bitset 一樣,區別在於其支援動態開空間,

bitset 則和我們一般的靜態陣列一樣,是在編譯時就開好了的。

那麼為什麼要用 bitset 而非 vector?

通過以下的介紹,你可以更加詳細的看到 bitset 具備的方便操作

#include // 包含 bitset 的標頭檔案

運算子¶

operator : 訪問其特定的一位

operator ==/!= : 比較兩個 bitset 內容是否完全一樣

operator &=/|=/^=/~ : 進行按位與/或/異或/取反操作

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

operator <> : 流運算子,這意味著你可以通過 cin/cout 進行輸入輸出

vector只具有前兩項

成員函式¶

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基本都沒有

作用¶一般來講,我們可以用 bitset 優化一些可行性 dp, 或者線篩素數 ( notprime 這種 bool 陣列可以用 bitset 開到 之類的)

它最主要的作用還是壓掉了記憶體帶來的時間優化, 的常數優化已經可以是複雜度級別的優化了,比如乙個 的 演算法, 顯然很卡,在常數大一點的情況下必然卡不過去,o(松)不能算!, 這時候如果我們某一維除以 32, 則可以比較保險的過了這道題

其實 bitset 不光是乙個容器,更是一種思想,我們可以通過手寫的方式,來把 long long 什麼的壓成每 bit 表示乙個資訊,用 stl 的原因更多是因為它的運算子方便

#include 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)

while

(isdigit(ch))

x *=ff;

}template

< typename t > inline void

write(t x)

int n, m, top, in

[maxn], b[maxn];

bitset

< maxn >a[maxn];

int lin[maxn], tot = 0

;struct

edge e[maxn];

inline

void add(int xx, int

yy)

void

topsort()

while(!q.empty())

}}int

main()

topsort();

for(int i = top; i >= 1; --i)

} for(int i = 1; i <= n; ++i)

return0;

}

AcWing 164 可達性統計

給定一張n個點m條邊的有向無環圖,分別統計從每個點出發能夠到達的點的數量。輸入格式 第一行兩個整數n,m,接下來m行每行兩個整數x,y,表示從x到y的一條有向邊。輸出格式 輸出共n行,表示每個點能夠到達的點的數量。資料範圍 1 n,m 30000 輸入樣例 10 10 3 82 3 2 55 9 5...

AcWing 164 可達性統計 搜尋

圖的遍歷 原題鏈結 本題思路 建立乙個圖的鄰接表 每個煉表裡都儲存了與之直連的點,那判斷乙個點的可達性,可求那些直連點自己煉表裡儲存點的並集 優化方案與技巧 bitset 將數壓縮為二進位制形式 內部表現 的十進位制 外部表現 陣列模擬鄰接表int e n ne n h n idx void add...

可達性統計

題目描述 給定一張n個點m條邊的有向無環圖,分別統計從每個點出發能夠到達的點的數量。n,m 30000。輸入第一行兩個整數n,m,接下來m行每行兩個整數x,y,表示從x到y的一條有向邊。輸出共n行,表示每個點能夠到達的點的數量。樣例輸入 複製樣例資料 10 10 3 82 3 2 55 9 5 92...