決定重新啟用markdown……只是因為它支援mathjax數學公式先說sat問題——指一種每個變數只有兩個值(true or false),並且給出一些限制,每個限制的基本形式為:noip考完,既輕鬆又無奈,回來慢慢填坑
這篇部落格也是拖了好久,通過kuangbin的部落格才弄懂2-sat的
\(a\ xor/or/and\ b\ xor/or/and\ c\ (etc.) = true\)
另外當每個限制涉及的變數只有兩個時,這類問題稱為2-sat問題,即 \(a\ xor/or/and\ b=true\),當然也可以限制值為 false,在這裡a,b也可以不保證不同。求這樣的問題的解,即每乙個變數選或不選。
假設現在有n個變數形成2-sat問題。
由於乙個變數要麼為true,要麼為false;我們可以把變數拆分成兩個點——乙個點表示true,另乙個表示false,這樣一來我們有 2n 個點,也就是 n 個點對;下面我們稱 a、a' 分別表示變數a選、不選。然後我們稱「乙個變數的狀態」為「這個狀態所對應的點選或不選」。
我們可以將點連邊,邊(x,y)表示選x就必須選y;下面舉兩種最基本的例子:
①選變數a就必須選變數b,則連 (a,b) (b',a) 兩條有向邊;即判斷某一方案是否可行。常用於檢驗二分答案。②必須選變數a,則連 (a',a) 的有向邊;
通過求強連通分量求解——如果 點v 和 點v' 同時存在於乙個強連通分量中,則說明從「選 變數v」 這一起點出發,可以推導出「不選 變數v」(反過來說也一樣),這樣就是不合法的。換句話說,點v 和 點v' 不能在同乙個強連通分量中。
求強連通分量的話這裡就用乙個常規的方法——先從某個點出發dfs遍歷能夠到達的點,當退出乙個dfs函式時,將當前的點壓入佇列中(建議手寫佇列,因為這裡只是用來儲存變數)。
上面是dfs1,每個點只能遍歷一次。
然後依次訪問佇列中的點,然後從當前列舉到的佇列中的點x出發進行dfs,將遍歷到的點所屬的「塊」(blk)都設為與點x相同的「塊」。這樣乙個「塊」就是乙個強連通分量。
最後列舉每乙個變數i,檢查 點i 和 點i' 是否在乙個強連通分量中,如果存在,則不可行。
[題意]
你需要在平面上放n個炸彈——放置第i個炸彈時,你需要在\((ax_i,ay_i)\)和\((bx_i,by_i)\)兩個位置中選擇乙個位置放置。每個炸彈的**半徑都是k,任意兩個炸彈的**範圍不能重疊(可以相切)。求k最大為多少。
[解析]
很容易想到二分答案,放置第i個炸彈時選擇 第乙個位置 定義為「選擇i」,選擇第二個位置 定義為「不選擇i」,這樣就形成了乙個2-sat問題。
根據二分出來的k可以求出重疊的炸彈,如果炸彈i與炸彈j重疊,則說明放炸彈i就不能放炸彈j,根據這個連邊,2-sat判斷合法性即可。
[源**]/*lucky_glass*/
#includeusing namespace std;
const int n=100,m=40000;
const double eps=1e-5;
int n;
struct points[n*2+5];
inline double dist2(int a,int b)
struct edgeedg1[m+5],edg2[m+5];
int hed1[n*2+5],hed2[n*2+5];
int cnt1,cnt2;
void addedge(int u,int v)
void clearmap()
int pop[n*2+5],blk[n*2+5];
bool vis[n*2+5];
int blkcnt;
void dfs1(int u)
void dfs2(int u)
bool check()
for(int i=0;i=eps){
double mid=(lef+rig)/2;
clearmap();
for(int i=0;i(坑還沒填完,下乙個弄懂再寫 tat)
更新-\(2018/11/17\);終於把後面一道題弄懂了
想法比較豐富……另外寫乙個blog……
2 SAT學習筆記
由對稱性解2 sat問題 2 sat解法 上面兩篇 很清楚的介紹了什麼是2 sat以及一些原理演算法 2 sat問題是圖論中乙個比較有意思的問題,重點是建圖,對於邊的意思,就是如果你選了i,就必須選j。2 sat問題有個很明顯的地方就是對於每個i,i包含兩個點,i表示選第乙個點,i 表示選第二個點,...
2 SAT學習筆記
2 sat問題指的是,給你若干個0 1變數。並給你一些限制,讓你求滿足這些限制的可行解 字典序最小的解 限制的種類包括以下幾種 1 a一定是1 2 a一定不是1 3 a,b至少有1個是1 4 a,b最多有乙個是1 5 a,b一定相同 6 a,b一定不同 一般思路是對於乙個變數,建立兩個變數 正,反 ...
2 sat學習筆記
例 struct twosat x xval or y yval void add clause int x,int xv,int y,int yv void init int n bool solve return1 為什麼不需要回溯呢?因為以前定下的變數如果在一輪dfs完之後沒有判為無解,那麼以...