Kuhn-Munkras算法流程:
(1)初始化可行顶标的值
(2)用匈牙利算法寻找完备匹配
(3)若未找到完备匹配则修改可行顶标的值
(4)重复(2)(3)直到找到相等子图的完备匹配为止
直接附代码
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的顶标能取到负值中的最大值。