插頭dp 筆記
插頭dp 筆記
限於我的水平,我們暫時只討論“簡單路徑問題”,並且例題不多
基礎知識
這個東西的全稱是 “基於連通性的狀態壓縮dp”。cdq有一篇論文講這個,是2008年的論文。
顧名思義,它乾的事情其實是,把“連通性”這個東西給壓縮起來了,並用這個壓縮方式,做一個dp。
插頭是啥
我們想要解決選路徑的問題。考慮現在有一個圖,現在加進來一個點,這個新點和原來的點有一些邊。
那選擇的路徑會發生怎麼樣的變化呢?對於原來的點,如果它已經有 \(2\) 的度數,那它就已經在路徑上,不能接更多的點了。而那些度數為 \(1\) 的點,就可以在邊上接一個點,這就是一個 “插頭”
怎麼壓縮連通性
對於一般圖,顯然,我們可以給一個連通塊標一個號。但是標號的方法有很多,我們需要找一種可以唯一確定,並且高效的記狀態的方法。
這很好搞,我們for一遍當前的點,碰到一個沒標號的,就 ++tot
。容易發現這樣標的方法顯然唯一,並且 tot
恰好等於連通塊數。標號完之後雜湊一波就行了。複雜度是 O(劃分數)。如果要求準確,使用map的話,可能要多個log。
有一類特殊問題:要求在網格圖上搞一條路徑,穿過整個網格。比如說,一條哈密頓路。
這個問題有著一個特殊性,就是我們只需要記一條輪廓線的 \(m+1\) 個插頭,就可以轉移。如下圖,每次我們討論一下這條輪廓線“折角”的那個位置的兩個頭怎麼變化就行了。
考慮這條輪廓線上的插頭的連通性,發現它一定是兩兩配對,並且不相交的,像括號匹配一樣。
為什麼?考慮一條穿過整個網格的路徑,它肯定會跨過輪廓線,偶數次。一頭進,一頭出,那麼這兩個點的連通性就是匹配的。
不相交這個性質,想象一下就知道了,因為相交就會有度數 \(>2\) 的點。
我們可以把它的狀態壓縮成:\(0/1/2\)。對於那些配對的點,我們令左邊那個是 \(1\),右邊那個是 \(2\),就像括號匹配一樣。對於沒有插頭的那些位置,我們給他一個 \(0\)。
比如上面那個圖,假設內部的連線情況如黃線所示,我們就給它一個 \(1,0,0,2,1,0,0,2\) 的狀態。
這可以用三進位制存,狀態數的數量是 \(O(3^{m+1})\)。
來個例題
1 Ural 1519 Formula 1 / HNOI2004郵遞員
哈密頓迴路計數。\(n,m\le 12\)。有障礙。(HNOI那個題沒有,不影響本質)
考慮每個格子,四個方向的連線情況,相當於在下面的 \(6\) 個東西里面選一個
相當於在 \(4\) 個方向裡選兩個,\({4\choose 2}=6\)。
狀態的表示已經整好了,考慮如何轉移。
影響轉移的只有“折角”的那兩個格子。討論它們插頭有無的情況。
設這兩個格子的狀態是 \(p,q\),\(p\) 在左,\(q\) 在右。
1. 都沒有,p=q=0
那往左,往上的插頭都不行,就只能有一種情況,就是往右、下的插頭。
然後我們需要把這兩個位置的狀態從原來的 \(p=0,q=0\) 變成 \(p=1,q=2\) ,因為這兩個插頭正好匹配
2. 其中一個有, pq=0, p+q>0
此時 \(p+q\) 為 \(p,q\) 中非 \(0\) 的那個
那我們的其中一根插頭,肯定在左、上裡面選,並且得選有插頭的那一個。另一根插頭,在右、下里面選。
轉移到的狀態肯定其中一個是 \(0\),另一個是 \(p+q\)。
有兩種,變成 \(0,p+q\) 和 \(p+q,0\)
3. 倆都有
最複雜的情況,此時我們還需要討論
3.1 兩個左/右括號,p=q=1/2
首先是 \(p,q\) 這兩個位置被合併,都變成 \(0\)
其實是,原來和 \(p,q\) 匹配的那兩個位置,現在也匹配上了,我們依次給它 \(1,2\)
3.2 右+左,p=2,q=1
原來 \(p,q\) 匹配的兩個位置,現在匹配上了,\(p,q\) 變成 \(0\)。
從 \(1,2,1,2\) 變成 \(1,0,0,2\)。我們發現,只需要改 \(p,q\) 倆位置,原來那些就自動匹配上了,根據括號序列的性質。
3.3 左+右,p=1,q=2
此時連線上 \(p,q\),就會有一個環出來。
而我們哈密頓路要求只有一個環,那一定是做到了最後一個格子,並且除了 \(p,q\) 位置都是 \(0\)。那此時會連出來恰好一個環。
這個情況直接轉移給答案就行了。
完畢。
此時把程式碼寫出來,發現就按這個討論的思路把程式碼實現了就行。(為啥有這麼毒瘤的討論,因為它本來就有這麼毒瘤的討論)
不是我對著程式碼在瞎講,是這程式碼就得對著討論寫
注意到兩個細節:
- 換行,此時必須行末沒有插頭才行。然後我們可以把這個空插頭,移到最前面,以方便下一行的轉移
- 障礙,這要求折角的兩個位置 \(p,q\) 都是 \(0\),並轉移到 \(0,0\) 的狀態
並小心另一個細節:當上面的兩個細節 同時出現 的時候。
(我就因為這個WA了好久)
(這是ural那個題的程式碼,HNOI那個題的程式碼要小小的寫個高精)
怎麼只有一個題啊
會整的會整的,會有更多的qaq