點選開啟鏈結
最大權匹配
km演算法
演算法步驟:
設頂點xi的頂標為a[i],頂點yi的頂標為b[i]
ⅰ.初始時。a[i]為與xi相關聯的邊的最大權值。b[j]=0。保證a[i]+b[j]>=w(i,j)成立
ⅱ.當相等子圖中不包括完備匹配時,就適當改動頂標以擴大相等子圖,直到找到完備匹配為止
ⅲ.改動頂標的方法
當從xi尋找交錯路失敗後,得到一棵交錯樹,它的全部葉子節點都是x節點。對交錯樹中x頂點的頂標降低d值,y頂點的頂標新增d值,對於圖中全部的邊(i,j),
能夠看到:
i和j都不在交錯樹中,邊(i,j)仍然不屬於相等子圖
i和j都在交錯樹中,邊(i,j)仍然屬於相等子圖
i不在交錯樹中。j在交錯樹中,a[i]+b[j]擴大。邊(i,j)不屬於相等子圖
i在交錯樹,j不在交錯樹中,邊(i,j)有可能增加到相等子圖中
為了使a[i]+b[j]>=w(i,j)始終成立,且至少有一條邊增加到相等子圖中,d=min,i在交錯樹中,j不在交錯樹中
時間複雜度:須要找o(n)次增廣路。每次增廣最多須要改動o(n)次頂標。每次改動頂標時列舉邊來求d值,複雜度為o(n2),總的複雜度為o(n4).簡單優化能夠減少到o(n3),每乙個y頂點乙個「鬆弛量」函式slack,每次開始找增廣路時初始化為無窮大。
在尋找增廣路的過程中,檢查邊(i,j)時。假設不在相等子圖中,則讓slack[j]變成原值與a[i]+b[j]-w[i,j]的較小值。這樣。在改動頂標時,取全部不在交錯樹中的y頂點的slack值中的最小值作為d值就可以。但還要注意一點:改動頂標後,要把全部的slack值都減去d。
#include #include #include #include #include #include #include #include #include #include #include #define for0(a,b) for(a=0;a=b;--i)
using namespace std;
typedef long long ll;
const int maxn = 310;
const int inf = 1e9;
/*km演算法
*o(nx*nx*ny)
*求最大權匹配
*若求最小權匹配,可將權值取相反數,結果再取相反數。
*/int nx, ny;
int g[maxn][maxn];
int linker[maxn], lx[maxn], ly[maxn];//y中各點匹配狀態,x,y中的頂標
int slack[maxn];
bool visx[maxn], visy[maxn];
bool dfs(int x)
return false;
}int km()
for(int x=0; xslack[i])
d = slack[i];
for(int i=0; i
hdu2255奔小康賺大錢
problem description 傳說在遙遠的地方有乙個非常富裕的村落,有一天,村長決定進行制度改革 重新分配房子。這可是一件大事,關係到人民的住房問題啊。村里共有n間房間,剛好有n家老百姓,考慮到每家都要有房住 如果有老百姓沒房子住的話,容易引起不安定因素 每家必須分配到一間房子且只能得到一...
HDU 2255奔小康賺大錢
hdu 2255奔小康賺大錢 題意 村里共有n間房間,剛好有n家老百姓,考慮到每家都要有房住 每家必須分配到一間房子且只能得到一間房子 由於老百姓都比較富裕,他們都能對每一間房子在他們的經濟範圍內出一定的 比如有3間房子,一家老百姓可以對第一間出10萬,對第2間出2萬,對第3間出20萬.每組資料的第...
HDU 2255 奔小康賺大錢
include include includeusing namespace std define inf 0x3f3f3f3f define n 300 10 int w n n n int lx n ly n 頂標 int match n int s n t n slack n s i 和t i...