Kuhn-Munkras算法流程:算法
(1)初始化可行頂標的值spa
(2)用匈牙利算法尋找完備匹配code
(3)若未找到完備匹配則修改可行頂標的值blog
(4)重複(2)(3)直到找到相等子圖的完備匹配爲止class
直接附代碼擴展
1 bool dfs(int x)//匈牙利算法尋找x的增廣路徑 以x爲根的M的交錯樹 2 { 3 int y,t; 4 visx[x]=true; 5 for(y=0;y<N;y++) 6 { 7 if(visy[y]) continue;//找增廣路徑的過程當中不妨問已經訪問過的頂點 8 t=lx[x]+ly[y]-g[x][y];//在相等子圖中尋找匹配的增廣路徑 9 if(t==0) 10 { 11 visy[y]=true; 12 if(linky[y]==-1||dfs(linky[y])) 13 { 14 linky[y]=x; 15 return true; 16 } 17 } 18 else//由於原本就須要將一條x頂點在交錯樹中,y頂點不在交錯樹中的邊擴展進交錯樹來 19 //因此只改變這些不在等子圖中的邊的y頂點的鬆弛量 20 { 21 if(slack[y]>t) 22 slack[y]=t; 23 } 24 } 25 return false; 26 } 27 //外層的匈牙利算法須要O(2)的時間,而修改頂標時因爲要枚舉全部的邊因此也須要O(2)的時間 28 //因此總時間是O(4) 29 //引入鬆弛量之後改變頂標就不須要枚舉每一條邊,只須要枚舉不在交錯樹中的y的鬆弛量,因此 30 //時間複雜度降爲O(3) 31 int KM() 32 { 33 int i,j,x,d,res=0; 34 memset(linky,-1,sizeof(linky)); 35 memset(lx,0,sizeof(lx));//x的頂標 36 memset(ly,0,sizeof(ly));//y的頂標 37 for(i=0;i<N;i++) 38 for(j=0;j<N;j++) 39 if(g[i][j]>lx[i]) 40 lx[i]=g[i][j];//一開始x的頂標爲全部與x相連的邊中權值最大的邊的權值,y的頂標爲0 41 for(x=0;x<N;x++) 42 {//在匈牙利算法中從每一個x出發尋找增廣路,若是找到就在匹配值上加1,這是爲了尋找最大匹配 43 //而在此處,必須找到完備匹配,因此對於每個x中的頂點,找到其增廣路就跳出,找不到的話 44 //就須要修改頂標值直至找到爲止 45 for(i=0;i<N;i++) 46 slack[i]=INF; 47 while(true) 48 {//無限循環直至找到完備匹配 49 memset(visx,false,sizeof(visx)); 50 memset(visy,false,sizeof(visy)); 51 if(dfs(x))break; 52 d=INF; 53 for(i=0;i<N;i++) 54 { 55 if(!visy[i]&&d>slack[i]))//注意是取全部不在交錯樹中的y頂點的鬆弛量的最小值做爲d的值 56 d=slack[i]; 57 } 58 for(i=0;i<N;i++) 59 if(visx[i]) lx[i]-=d; 60 for(i=0;i<N;i++) 61 if(visy[i]) ly[i]+=d; 62 else slack[i]-=d; 63 } 64 } 65 for(i=0;i<N;i++) 66 if(linky[i]!=-1) res+=g[linky[i]][i]; 67 return res; 68 }
plus:若要求最小權匹配,只需將全部邊權值取反,同時讓x的頂標能取到負值中的最大值。循環