做了一些題之後感覺自己的知識儲備真的太少了,很多東西都不知道;
題目大意:
乙個矩形中,有n個城市』*』,現在這n個城市都要覆蓋無線,若放置乙個基站,那麼它至多可以覆蓋相鄰的兩個城市。
問至少放置多少個基站才能使得所有的城市都覆蓋無線?
解題思路:
思前想後,依稀可以認為是一道求二分圖的最小路徑覆蓋問題
(注意不是最小點覆蓋)
那麼接下來需要確認的是,
究竟是求 有向二分圖的最小路覆蓋,還是求 無向二分圖的最小路覆蓋
因為有向和無向是截然不同的計算方法。
要確認是構造有向圖,還是構造無向圖,那麼就需要先根據題意,看看構造二分圖時所使用的方式,更適合構造哪一種二分圖。
然後就進入了本題難點:如何構造二分圖
首先要明確的是,輸入的一堆「圈圈星星」可以看做是一張大地圖,地圖上有所有城市的座標,但是這裡有乙個誤區:不能簡單地把城市的兩個x、y座標作為準備構造的二分圖的兩個頂點集。
城市才是要構造的二分圖的頂點!
構造方法如下:
例如輸入:
*oo***
o*o時,可以抽象為乙個數字地圖:
100234
050數字就是根據輸入的城市次序作為該城市的編號,0代表該位置沒有城市。
然後根據題目的「範圍」規則,從第乙個城市開始,以自身作為中心城市,向四個方向的城市進行連線(覆蓋)
因此就能夠得到邊集:
e12 e21 e32 e43 e53
e23 e34
e35可以看到,這些邊都是有向邊,但是每一條邊都有與其對應的一條相反邊。
即任意兩個城市(頂點)之間的邊是成對出現的
那麼我們就可以確定下來,應該 構造無向二分圖(其實無向=雙向)
因為若要構造有向的二分圖時,需要判斷已出現的邊,是很麻煩的工作
為了把有向圖g構造為無向二分圖,這裡需要引入乙個新名詞「拆點」
其實就是把原有向圖g的每乙個頂點都」拆分(我認為複製更準確)」為2個點,分別屬於所要構造的二分圖的兩個頂點集
例如在剛才的例子中抽出一條有向邊e12舉例說明:
複製頂點1和頂點2,使得1,2∈v1; 1』,2』∈v2 ,不難發現|v1|=|v2|
根據邊e12和e21,得到無向二分圖:
那麼同理就可以得到剛才的例子的 無向二分圖為:
再繼而通過無向二分圖,以v1的元素作為row,v2的元素作為col,構造 可達矩陣 儲存到計算機
1』 2』 3』 4』 5』
1 f t f f f
2 t f t f f
3 f t f t t
4 f f t f f
5 f f t f f
接下來就是要求這個 無向二分圖的最小路徑覆蓋 了
利用公式:
無向二分圖的最小路徑覆蓋 = 頂點數 – 最大二分匹配數/2
頂點數:就是用於構造無向二分圖的城市數,即進行「拆點」操作前的頂點數量
最大二分匹配書之所以要除以2,是因為進行了「拆點」擦奧做做使得匹配總數多了一倍,因此除以2得到原圖的真正的匹配數
最後剩下的問題就是求最大二分匹配數了,用匈牙利演算法,這就不多說了,參考poj3041的做法,基本一摸一樣。
從這道題得出了乙個結論:
當二分圖的兩個頂點子集基數相等時,該二分圖所有頂點的匹配數 等於 任意乙個頂點子集匹配數的2倍
其實匈牙利演算法解題是極為簡單的,但是圖論的難並不是難在解答,而是建圖的過程,也難怪會有牛曰:用匈牙利演算法,建圖是痛苦的,最後是快樂的。
//memory time
//420k 16ms
#includeusing namespace std;
int ipmap[41][11]; //標記存在城市'*'的位置,並依次記錄城市的編號
int ip; //城市編號(最終是城市數量)
int v1,v2; //二分圖的兩個頂點集
int m; //最大二分匹配
bool city[401][401]; //標記兩個城市之間是否能連通
//通過「拆點」操作,把每乙個城市拆分為2個,分別屬於所構造的二分圖的兩個點集
bool vist[401];
int link[401];
int dire_r[4]=;
int dire_c[4]=; //分別對應四個方位 上 下 左 右
/*hungary algorithm*/
bool dfs(int x)
} return false;
}void search(void)
return;
}int main(void)
/*structure the bipartite graphs*/
for(i=1;i<=h;i++)
for(j=1;j<=w;j++)
if(ipmap[i][j])
for(int k=0;k<4;k++)
//二分圖構造完畢後,之後的問題就和poj3041一樣處理了
v1=v2=ip;
/*增廣軌搜尋*/
search();
/*output*/
cout<
} return 0;
}
樹上最小邊覆蓋問題
1077.皇宮看守 對於一條邊,可以由父節點覆蓋,或者子節點覆蓋,f u 0 表示該節點不放士兵,f u 1 表示該節點放士兵.當該節點不放時,只有由所有子節點放的情況轉移 當該節點放時,可以由子節點放或不放的情況轉移而來 includeusing namespace std const int n...
POJ 3020(最小路徑覆蓋 拆點)
題意 乙個矩形中,有n個城市 現在這n個城市都要覆蓋無線,若放置乙個基站,那麼它至多可以覆蓋相鄰的兩個城市。問至少放置多少個基站才能使得所有的城市都覆蓋無線?思路 每個城市才是要構造的二分圖的頂點,先把每個 用數字1 n標記起來,然後構造無向二分圖,無向二分圖的構造需要拆點,即12之間的雙向邊要拆成...
HDU 1350 最小邊覆蓋
將某個人的行程視為二分圖中的乙個節點,用結構體記錄每個節點的資訊 起點時間,終點時間,位置 然後對於每個節點,看它結束後能否提前趕到其他節點,能的話就加邊。然後就用二分圖匹配,算出最小邊覆蓋就可以了。為什麼是最小邊覆蓋,因為乙個計程車走一條邊,囊括所有節點的最少的邊數就是我們要求的最少計程車數。記得...