簡單環(狀壓 dp,詳細注釋)

2021-09-27 21:21:11 字數 1624 閱讀 2106

參考部落格:牛客網 wannafly挑戰賽17 c-簡單環 狀壓dp

題目描述

給定一張n個點m條邊的無向圖,求出圖中所有簡單環的數量。(簡單環:簡單環又稱簡單迴路,圖的頂點序列中,除了第乙個頂點和最後乙個頂點相同外,其餘頂點不重複出現的迴路叫簡單迴路。或者說,若通路或迴路不重複地包含相同的邊,則它是簡單的)

輸入描述:

第一行三個數n m k (k在輸出描述中提到)

接下來m行每行兩個數u,v表示u到v之間存在一條邊(無重邊)

輸出描述:

輸出k行每行1個整數

第i個數表示長度%k==i-1的簡單環的數量(對998244353取模)

(只記錄長度大於2的簡單環的數量)

輸入4 6 3

1 22 3

3 44 1

2 41 3輸出4

30備註:n<=20

m<=n*(n-1)/2

k<=n

思路把路徑轉化為二進位制狀態,設定乙個陣列 f[i][j] 表示路徑終點為 j ,二進位制下狀態為i的數目,為了避免重複,可以把 i 最小位的 1 設為起點,列舉狀態和終點,若終點到起點有直接連線則為答案。最後每條環仍會重複計算兩次,需要求除法逆元去重。

#include

#include

#include

#include

#include

using namespace std;

#define ll long long

// n 個點,m 條邊,k 行輸出

int n, m, k;

//記錄能走的路

bool vis[21]

[21];

//f[i][j]儲存路徑終點為 j,二進位制下狀態為 i 的個數

int f[

1<<21]

[21];

//ans 記錄最後的結果,只用 0 ~ k-1

//len 記錄不同 i 長度環的個數

int ans[21]

, len[41]

;const

int mod =

998244353

;//返回二進位制下最低位 1 的位置

intlowbit

(int x)

intmain()

}//初始化 f

for(

int i =

1; i <= n; i++

)for

(int i =

2; i <

1<<

(n +1)

; i +=2

)}// cout<<"i: "(int j =

1; j <= n; j++

)//從 s+1 開始列舉,避免重複計算路徑

for(

int k = s +

1; k <= n; k++)}

}}}//只記錄長度大於 2 的簡單環的數量

for(

int i =

3; i <= n; i++

)//每個環仍舊會被重複計算兩次

for(

int i =

0; i < k; i++

)return0;

}

狀壓DP(超詳細!!!)

狀態壓縮動態規劃,就是我們俗稱的狀壓dp,是利用計算機二進位制的性質來描述狀態的一種dp方式。很多棋盤問題都運用到了狀壓,同時,狀壓也很經常和bfs及dp連用。狀壓dp其實就是將狀態壓縮成2進製來儲存 其特徵就是看起來有點像搜尋,每個格仔的狀態只有1或0 是另一類非常典型的動態規劃 舉個例子 有乙個...

hdoj 3555 數字dp,詳細注釋

數字dp可以解決類似這樣一道給你上下界,求裡面符合要求的數字,暴力肯定超時的.下面給出帶注釋的 include includetypedef long long ll using namespace std ll dp 20 2 ll dight 20 ll dfs ll len,bool if4,...

簡單的期望 狀壓dp

dp定義真的神,直接的想法是 f x maxn 為第 x 個操作,狀態 maxn maxn 1 200,好像沒有暴力分高 實際上我們可以這樣定義 f x maxn len 0 1 表示後八位 maxn 第九位0 1,第九位之後連續長度為 j 概率 為什麼這樣定義 實際上質因數分解後2的次數就是後面0...