- 首先最小覆蓋集可以用二分圖匹配求出來記爲ans。
然後是怎麼來求最小覆蓋集。
首先枚舉每個已經匹配了的點,如果去掉這個點以及和這個點所相連的所有邊, 如果剩下圖的二分圖的最大匹匹配如果是ans-1,那麼這個點就是最小覆蓋集中的點,如果最大匹配還是ans,那麼這個點就不是最小覆蓋集點,因爲如果選這個點,那麼新加入的那個點肯定是在去掉的這個點一邊,但是他是不能被去掉的這個點所覆蓋。
接下來是怎麼求解最小字典序,從0到n-1 ,如果找到一個點是覆蓋點,那麼就把他加入最小覆蓋點集中,並去掉和這個點所連的所有邊。
其實這道題並不用每次都找匹配點,因爲,我們去掉一個點的話,那麼用原來和他匹配的點找增廣路,那麼如果找到新的增廣路,而原來的 點不便,那麼最大匹配還是ans-1 ,所以這樣的話可以極大的節約時間。
可以看看這邊文章http://blog.csdn.net/mofixroot/archive/2009/10/20/4706113.aspx
別人給我的思路
首先構圖跑SAP(匈牙利應該也行,但我對匈牙利的實現細節不瞭解(我從未實現過匈牙利),所以不敢妄加說明)求出最小點覆蓋的數量……這個沒問題吧……
然後把匹配邊、哪些端點被匹配了也都搞出來……這個也沒問題吧……
然後我們就能發現,在每條匹配邊中,有且僅有一個端點會被入選到最終結果中。
我們不妨思考一下,一個端點可以進入最終結果的條件是什麼?可以發現,如果這個點是被匹配點,且刪掉這個點和與其相連的所有邊後的新圖最小點覆蓋數目比當前的數目小1,那麼這個點是有資格作爲最小覆蓋中的點的,否則一定不能。
接下來的事情就是字典序的問題了。我們不妨從1~n枚舉點,如果這個點有資格進入最小點覆蓋集,就讓他進入,然後刪掉這個點以及和它相連的所有邊。繼續這個過程,顯然最後得到的就是字典序最小的點覆蓋集了。
事
實上,真正實現時大可不必這麼麻煩。在判定一個點是否可行時,直接給這條匹配邊的另一個端點一個單位流量,然後判定可否增廣(虛擬的增廣,一個dfs即
可)。如果可以增廣,這個點就不能進入最小點覆蓋集,收回剛纔給的流量,否則這個點進入最終答案,那個流量不必收回,因爲這時另一個匹配點還是可以被其他
點匹配的。
時間複雜度:匹配的複雜度:O(sqrt(n)*m),得出最終答案的複雜度:O(n*m),總:O(nm)
具體見代碼。
2011-04-2120:22:25