2-sat 部分題目


記錄一些做過的 2-sat 題目

P4171 [JSOI2010]滿漢全席

洛谷 P4171bzoj 1823

很裸的 2-sat
題意:\(n\) 種食材,每種可以按照滿式或漢式來烹飪,有 \(m\) 個要求,每個要求所有做出的菜品中,必須有指定的兩個 滿式/漢式 烹飪的第 \(x\) 種食材 中,至少一個
多測

就把每個食材,拆乘用滿式和用漢式兩個點,然后題目中給出的是“或”的關系,用經典 2-sat 模板的方法建圖跑 tarjan 就行
其實 滿式和漢式 對應的就是經典模型中的 真和假

代碼

P5782 [POI2001]和平委員會

洛谷 P5782

每個黨在議會中有 \(2\) 個代表。代表從 \(1\) 編號到 \(2n\)。 編號為 \(2i-1\)\(2i\) 的代表屬於第 \(i\) 個黨派。
選一些人當代表,滿足:

  • 每個黨派都在委員會中恰有 \(1\) 個代表。
  • 如果 \(2\) 個代表彼此厭惡,則他們不能都屬於委員會。

給出互相厭惡的信息,求是否有滿足要求的選法,如果有,升序輸出任意一種

也是顯然的 2-sat
對於給出的互相厭惡的兩個人,先判一下在他們在自己的黨派中分別是第幾個人
對於每個黨,拆成兩個點,然后每個點代表是選第一個人還是選第二個
連邊的依據就是,如果選了這個人,一定要再選哪個人

我的寫法中是,每個黨中第一個人用 \(1\)\(n\),編號,第二個人用 \(n+1\)\(2n\) 編號
給出的信息的連邊方式是,對於互相厭惡的每一方,都向對方的黨派中,的另一個人連邊,表示如果選擇這個人,在對方黨派中,就必須選另一個人(因為不能同時選這個人和對方)

然后跑 tarjan 就行了
代碼

P6378 [PA2010]Riddle

洛谷 P6378

\(n\) 個點 \(m\) 條邊的無向圖被分成 \(k\) 個部分。每個部分包含一些點。
請選擇一些關鍵點,使得每個部分 至多 有一個關鍵點,且每條邊 至少 有一個端點是關鍵點。

比上面兩個稍微難點
還是把每個點拆成兩個,分別表示這個點選為關鍵的還是不選
\(1,\cdots ,n\) 的編號表示選,\(n+1,\cdots ,2n\) 的編號表示不選

首先考慮第二條限制,每條邊 至少 有一個端點是關鍵點
\((u+n,v),(v+n,u)\) 兩條邊,表示一段如果不選,一定能導出另一端要選

再考慮第一種,首先有種朴素的想法,就是每一個點,設為 \(x\),設和它在同一個部分內的點編號分別是 \(a_i\),用 \(x\) 分別向 \(a_i+n\) 連邊
就是如果 \(x\) 被選了,一定能導出 \(a_i\) 都不能選
但邊數達到了 \(n^2\),不可行

可以用一種 前綴和優化,以前並沒有聽說過這種方法,還是看來題解才知道的
要新建一堆點,\(pre_i\) 表示在當前的這個部分,前 \(i\) 個點中,有一個點已經被選了,而 \(pre_i'\) 表示前 \(i\) 個點,一個都沒被選
然后也是用 2-sat 的連邊規則,假設某個點表示的信息成立,那么就用它,連向由它表示的這個信息,一定能導出的信息,所對應的點

具體的連邊方式比較復雜,可以想到,如果當前在考慮一個部分的第 \(i\) 個點,與它有關的有 \(a_i,a_i',pre_i,pre_i',pre_{i-1},pre_{i-1}'\),這里是用 \(a_i,a_i'\) 分別表示代表信息第 \(i\) 個點 選/不選 的點
然后如果很懵的話可以 \(6\times 5=30\) 次兩兩分別枚舉,看一下有沒有關系,看起來麻煩,其實有好多一想就知道沒關系的可以直接跳過了
下面的括號表示連邊,是有向的

  • \((a_i,a_i'),(pre_i,pre_i'),(pre_{i-1},pre_{i-1}')\),這些並不在 2-sat 連邊考慮范圍內,然后把他們反過來也是一樣
  • \((a_i,pre_i),(a_i,pre_{i-1}')\),選了第 \(i\) 個,前 \(i\) 個中有被選的,前 \(i-1\) 個沒有
  • \(a_i',pre_i,pre{i-1}'\),這三個信息並不能推出什么,所以沒有它們的出邊
  • \((pre_i',a_i'),(pre_i',pre_{i-1}')\),顯然
  • \((pre_{i-1},pre_i),(pre_{i-1},a_i')\),前 \(i-1\) 個中有被選的,前 \(i\) 個肯定也有,且第 \(i\) 個不能選

就可以了,題目也並沒有要求給出方案
代碼中,用 \(1\)\(n\) 表示 \(a_i\)\(n+1\)\(2n\) 表示 \(a_i'\)\(2n+1\)\(3n\)\(pre_i\)\(3n+1\)\(4n\)\(pre_i'\)
代碼

P3825 [NOI2017]游戲

洛谷 P3825bzoj 4945


\(n\le 5\cdot 10^4,m\le 10^5,d\le 8\)

如果沒有 \(\texttt{x}\) 地圖,那么對於每一場比賽,都只能使用兩種車子
那么對每個比賽,可以用兩個點,分別表示對於當場比賽,用的是能用的車子中的第幾個(比如一場比賽不能用 \(\texttt{A}\),那么 \(\texttt{B}\) 就是第一個,\(\texttt{C}\) 就是第二個
直接按 2-sat 建圖跑 tarjan
考慮如何建圖,下面描述中,字母意義就對應了題目中游戲要求描述的四元組中的字母,設第 \(i\) 個比賽不能用車 \(s_i\)

  • \(s_i=h_i\),不能用 \(h_i\),說明這種情況永遠不會發生,直接忽略就行
  • \(s_j=h_j\)\(j\) 比賽不能用 \(h_j\),說明我們不能讓這種情況發生,否則就違反了規則,那么由 \(h_i\),向連邊比賽 \(i\) 能用的另一個車連邊,表示如果用車 \(h_i\) 成立(這是不符合我們要求的),就要強制它選另一輛,也就是讓另一個車成立
  • 其它情況。由 \(h_i\)\(h_j\) 連邊就行,意義就是題目中要求的,\(i\)\(h_i\)\(j\) 必須用 \(h_j\)

如果 tarjan 判斷成立,按照 tarjan 縮點時強連通分量與拓撲序相反的性質,就能構造出一組解

那么有地圖 \(\texttt{x}\) 怎么辦?
由於 \(\texttt{x}\) 很少,所以可以 \(2^d\) 枚舉每一個 \(\texttt{x}\)\(\texttt{a}\)\(\texttt{b}\),這樣分別能使用 \(\texttt{A,B}\) 車和 \(\texttt{B,C}\) 車,包含所有情況,就不用考慮 \(\texttt{x}\) 是地圖 \(\texttt{c}\) 的情況了

所以復雜度 \(O(2^dm)\),洛谷bzoj都能過,但uoj加了一組惡心的extra,被卡成了97,把遞歸改成循環再加上火車頭還是不行/kk
代碼

P3513 [POI2011]KON-Conspiracy

洛谷P3513

Byteotia 的領土被占領了,國王 Byteasar 正在打算組織秘密抵抗運動。國王需要選一些人來進行這場運動,而這些人被分為兩部分:
一部分成為同謀者活動在被占領區域,另一部分是后勤組織在未被占領的領土上運轉。但是這里出現了一個問題:

  • 后勤組織里的任意兩人都必須是熟人,以促進合作和提高工作效率。
  • 同謀者的團體中任意兩人都不能是熟人。
  • 每一部分都至少要有一個人。

國王想知道有多少種分配方案滿足以上條件,當然也有可能不存在合理方案。

比較有思維難度,思路來自這個blog:https://www.cnblogs.com/chenyushuo/p/5128665.html

首先,可以用一個很顯然的 2-sat 求出一種安排方式,具體方法是 \(i\) 認識 \(j\),就連邊 \(i+n,j\),否則連 \(i,j+n\)
其中 \(1\cdots n\) 是后勤,\(n+1\cdots 2n\) 是同謀

然后從這種方式看看能轉變成幾種其它方式,顯然不能同時讓兩個人從一個集合到另一個集合(比如兩個互相認識的后勤同時到了同謀,那么它們互相認識就出現了問題)
所以轉換方式是,一個人自己轉變集合,或者兩個集合交換一個人

首先定義 \(x\) 的“沖突點”,如果 \(x\) 是后勤,那么沖突點是在同謀中的 \(x\) 認識的人,如果 \(x\) 在同謀,沖突點是在后勤中 \(x\) 不認識的人
\(x\) 的沖突點個數為 \(num_x\)

  • \(num_x>1\),則無法讓 \(x\) 到另一個集合
  • \(num_x=1\),需要交換 \(x\) 和他的唯一一個沖突點,但是如果它的沖突點的 \(num\) 不為 \(0\),也不能交換(兩個點顯然不能互為沖突點,那么如果它的沖突點也有沖突點,就肯定和它的集合內的某個點沖突,除非和這個沖突的點互換,它的沖突點是不能來的它的集合的)
  • \(num_x=0\),可以直接把 \(x\) 放到對面(如果 \(x\) 所在集合大小大於 \(1\)),也可以和對面某個沖突點個數為 \(0\) 的點呼喚

最后這個兩個集合中,沖突點為 \(0\) 的點互換產生的答案,可以拿兩遍沖突點個數為 \(0\) 的點的個數一相乘得到
可以想到,這樣統計答案包含了所有情況

代碼

POJ2749 Building roads

給出一些點和它們的坐標,以及兩個鏈接點,所有點都要鏈接到恰好一個鏈接點上
給出 \(A\) 對點,這些點任意一對不能鏈接同一個鏈接點。還有 \(B\) 對點,任意一對必須連接到一個鏈接點
問有沒有可行方案,如果有,兩個點之間最大距離的最小值是多少,距離按曼哈頓距離計算

每個點拆成 連到第一個點 和 連到第二個點,然后二分一個最大距離,就可以得到關於距離的限制條件,連邊即可

代碼

LOJ#6036.「雅禮集訓 2017 Day4」編碼
P5332 [JSOI2019]精准預測
這倆題細節好像挺多,做了一上午沒做出來自閉了/kk
LOJ#571.「LibreOJ Round #11」Misaka Network 與 Accelerator,一開始以為是個線段樹優化連邊的題,后來寫着寫着發現不對,看網上說要用邊分治,之后應該就要學這一塊了,到時候應該會補

然而難度稍大的我似乎都沒做qaq


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM