1. 程式人生 > 其它 >2.10 模擬賽總結

2.10 模擬賽總結

2.10 模擬賽總結

A. 希望

題意

給一張 \(N\times M\) 的網格圖,圖中存在若干關鍵點,其中關鍵點一定不在圖的最左或最右兩列。

你需要走一條包含點 \((1,1)\) 的歐拉回路,滿足:

  1. 該回路經過所有關鍵點;
  2. 只有在圖的最左邊或最右邊兩列時可以沿縱向走,在任意時刻都可以沿橫向走。

求路徑的最小長度。

\(N\le10,M\le50\)

做法

我們記圖中第一列和最後一列的所有點叫邊緣點。

注意到若某個關鍵點被經過了,則其所在的那行裡,一定存在一個邊緣點被經過了一次,

因為對於這一行內的一個關鍵點,只有到達了這一行的邊緣點後,才可能沿橫向走到該關鍵點。

同時,當每個邊緣點是否被經過的狀態確定後,不同行內部如何抉擇是互不影響的,

那我們現在來討論一下,對於具體的一行裡兩個邊緣點狀態的所有可能,分別該如何決策。

顯然,一行內的一個關鍵點不會被經過多次,否則我們一定可以將方案調整成只經過一次且會更優,

而我們進入行的途徑只有邊緣點,故我們必然分別從兩邊緣點往行內走 \(x\in[0,m]\) 步,

再返回當前邊緣點或者到達另一端的邊緣點後繼續沿縱向行走。

而當邊緣點未經過過時需滿足步數 \(x=0\),且兩邊走的步數之和小於 \(m\)

形式上的,我們記該行左右兩個邊緣點分別是 \(u\)\(v\),如果一個點 \(p\) 曾被經過,則其狀態 \(s(p)=1\)

首先,如果 \(s(u)=1\),則我們可以選擇從 \(u\)

出發到該行最右端的關鍵點再回到 \(u\) 點或繼續走到底;

其次,如果 \(s(v)=1\),則我們可以選擇從 \(v\) 出發到該行最左端的關鍵點再回到 \(v\) 點或繼續走到底;

最後,如果 \(s(u)=s(v)=1\),則我們可以選擇分別從 \(u,v\) 出發,分別到達一對相鄰關鍵點再返回。

當然,如果該行內沒有關鍵點,我們也可以選擇不管這一行。

又因為不同行內部如何抉擇是互不影響的,

所以容易想到的是利用 狀壓DP 的思想,即記錄當前座標以及當前每一行的行走情況來求解。

具體來說,我們設計一個含有 \(O(N5^N)\) 個狀態的 狀壓DP,即:

\(f(i,j,S)\)

代表當前在第 \(i\) 行的第 \(j\) 個邊緣點,其中第 \(t\) 行的狀態是 \(S\) 在五進位制下的第 \(t-1\) 位,

該位的五種不同的值,分別代表了該行:

從未走過,被橫穿了一次,左邊緣點曾被經過,右邊緣點曾被經過,兩邊緣點都曾被經過。

這樣的話,我們只需要處理每種狀態是否可能出現以及出現這種狀態的花費,

最後在額外計算每行沒有處理過的花費即可。

但上述方法並不能通過,而實際上這個做法還有優化空間。

但是我們發現,在轉移時,下列三種選擇對原狀態造成的影響是類似的:

橫穿一行,只從左邊緣點進入並返回,以及只從右邊緣點進入並返回。

我們發現,這三種選擇都讓當前一整行不再需要考慮,而唯一的區別是最後新到達的邊緣點位置,

故我們可以考慮不單獨記錄被橫穿,而是記錄一個數量為 \(4^N\) 的狀態,其中第 \(t\) 行對應的狀態有:

從未走過,左邊 / 右邊走了一部分但沒有走完整行,整行的關鍵點全走了一次。

這樣的狀態就顯然是是完備且可以轉移的了,

時間複雜度為 \(O(N^24^N)\),空間複雜度為 \(O(N4^N)\)

C. 命運

題意

給一張 \(N\) 個點 \(M\) 條邊的無向圖,請求出圖的所有滿足不存在三元環的點匯出子圖個數。

\(N,M\le60\)

做法

首先,暴力的做法是列舉原圖中每個點的狀態,即該點是否出現在匯出子圖中,

再對每個匯出子圖暴力的統計其是否包含三元環,這樣的複雜度是 \(O(2^NN^3)\) 的。

我們考慮優化這個暴力,一個很靈巧的想法是考慮能否只列舉一部分點而達到同樣的效果。

那假設我們只枚舉了點集 \(S\) 中的點,記不在 \(S\) 中的點集為 \(T\),我們考慮 \(T\) 滿足什麼性質時能正確計數。

我們發現,如果 \(T\) 是若干個樹,環,或鏈這樣的一些特殊結構時,我們就可以採用 DP 來計數,

那也就是說,我們只要能恰當的去選這個 \(S\) 集合,

使得 \(S\) 的大小足夠小,且 \(T\) 中只有我們希望出現的結構,那麼這個問題就解決了。

那最終的問題就是如何選 \(S\) 集合,我們只需要採用如下的方法即可:

我們建一張新圖 \(G\),初始為原圖,我們一次次從將 \(G\) 中所有度數大於 \(2\) 的點和與其相連的邊刪除,

最後無法從 \(G\) 中刪點時,所有我們刪去的點集就是我們需要的 \(S\) 的一個足夠優的解。

為什麼?首先,這樣得到的 \(S\) 對應的 \(T\) 一定只存在若干個鏈和環,原因是所有點的度數都小於 \(3\)

而只有鏈和環能滿足這個度數的要求,而因為一次刪點的同時會伴隨著刪至少 \(3\) 條邊,

故總刪邊次數不超過 \(\frac{M}{3}\) 次,故 \(S\) 的大小最大也就是 \(\frac{M}{3}\)

那麼,我們的時間複雜度就是 \(O(2^{\frac{M}{3}}N)\) 的,已經足以通過本題。

最後,我們討論怎麼使用 DP 來對 \(T\) 計數,這個是好做的,具體來說:

首先,每個 \(T\) 中的連通塊是獨立的,我們可以分開計數,最後再把方案數乘在一起;

而對於一個連通塊,其只能是一條鏈或環,我們考慮對 \(T\) 方案的限制只有如下兩種:

其一是,一個 \(S\) 中出現在匯出子圖中的點與 \(T\) 中的一對相鄰點分別有邊,

則這對點不能同時出現在匯出子圖中,

其二是,一對 \(S\) 中出現在匯出子圖中的相鄰點與 \(T\) 中的一個點分別有邊,

則這個 \(T\) 中的點不能出現在匯出子圖中。

也就是說,在列舉 \(S\) 中點的狀態後,我們對 \(T\) 的限制只有一個點不能選,或一對相鄰點不能同時選。

而這些限制在鏈或環上都是好處理的,我們直接 DP 計數即可。