給定乙個n行m列的棋盤,已知某些格仔禁止放置。
問棋盤上最多能放多少個不能互相攻擊的車。
車放在格仔裡,攻擊範圍與中國象棋的「車」一致。
第一行包含三個整數n,m,t,其中t表示禁止放置的格仔的數量。
接下來t行每行包含兩個整數x和y,表示位於第x行第y列的格仔禁止放置,行列數從1開始。
輸出乙個整數,表示結果。
示例1
8 8 0
8
先分析出之前講的 \(0/1要素\)
。「1要素」:
每行、每列只能放1個車(不然就能互相攻擊到)。某個格仔 \((i,j)\) 如果放了車,就等於占用了第 \(i\) 行與第 \(j\) 列放車的「名額」
因此,我們可以把行、列看作節點,一共\(n+m\)個節點。如果格仔\((i,j)\) 沒有被禁止,就在第 \(i\)行對應的節點與第 \(j\) 行對應的節點之間連無向邊。
「0要素」:
每個車顯然不能既在第 \(i_1\) 行又在第 $ i_2$ 行,所以兩個「行」對應的節點之間沒有邊。對於「列」也同理。
因此,剛才構建的無向圖是二分圖,我們可以把n個「行節點」作為左部,m個列節點」作為右部。
更在不能互相攻擊的前提下放置的車最多,就是求上述分圖的最大匹配,時間複雜度為 \(o((n +m)*nm)\)。
ac**
#includeusing namespace std;
int n, m, t, f[210], b[210], ans;
bool a[210][210], v[210];
bool dfs(int x)
}return false;
}int main()
for (int i = 1; i <= n; ++i)
cout << ans << endl;
}
完備匹配:
給定一張二分圖,其左部、右部點數相同,均為 \(n\) 個節點。如果該二分圖的最大匹配包含 \(n\)
條匹配邊,則稱該二分圖具有完備匹配。
多重匹配:
給定一張包含 \(n\) 個左部節點、\(m\) 個右部節點的二分圖。從中選出盡量多的邊,使第 \(i (1 <= i <=n)\) 個左部節點至多與 \(kl_i\) 條選出的邊相連,第 \(j(i <= j <= m)\) 個右部節點至多與 \(kr_j\) 條選出的邊相連。該問題被稱為二分圖的多重匹配。
當\(kl_i=kr_j=1\) 時,上述問題就簡化為二分圖最大匹配。因此,多重匹配是乙個廣義的「匹配」問題,每個節點可以與不止一條「匹配」邊相連,但不能超過一.個給定的限制。
多重匹配一般有 四種解決方案:
1.拆點。把第 $i $個左部節點拆成 \(kl_i\)個不同的左部節點,第j個右部節點拆成 \(kr_j\)個右部節點。對於原
圖中的每條邊 \((i,j)\), 在i拆成的所有節點與 \(j\) 拆成的所有節點之間連邊。然後求解二分圖最大匹配。
2.如果所有的 \(kl_i= 1\),或者所有的 \(kr_j= 1\),即只有一側是「多重」匹配,不妨設左部是「多重」的,那麼可以
直接在匈牙利演算法中讓每個左部節點執行 $kl_i $ 次dfs。
3.在第2種方案中,當然也可以交換左右兩部,設「右部」是多重的,修改匈牙利演算法的實現,讓右部
節點可以匹配 \(kr_j\)次,超過匹配次數後,就要依次嘗試遞迴當前匹配的 \(kr_j\)個左部節點,看能否找到增廣路。
4.網路流。這是最一般也是最高效的解決方法。但博主尚未學習(可能以後會補上)。
C 中 x與0x的區別
首先這兩個均表示16進製制,但是用法有所不同。x主要是用於字元的表示 如char ch xa 那麼ch這個字元所代表的是什麼呢?正如上面所說的 x代表的是16進製制,16進製制中的a在十進位制中代表10,那麼ch這個數就代表著序號為10的ascii碼所代表的字元,即 n換行符。0x雖然也代表十六進製...
C 0 x中 C 的未來
0 x的工作名稱的新標準c 增加了許多,我將在這一系列c 11的語言功能。2011年9月,c 0 x的正式出版為新的c 11標準,現在許多編譯器提供了一些核心c 11功能的支援。c 11包括廣泛的特點 主要的新功能,像拉姆達的支援和 移動語義 通過自動關鍵字型別推斷可用性改進,例如,簡化迴圈容器,許...
C 0x11中列舉的問題
c 11中新增的強型別列舉,確實可以解決此前版本中列舉的作用域問題,但是隨之也帶來一些其他問題。強型別列舉的宣告方式為 enum class enumname value1,value2 在編碼中,我以前比較習慣對列舉值應用位運算,比如 和 但是對於c 11中的強型別列舉,則無法再應用位運算。比如 ...