最大權匹配KM算法模板

 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的頂標能取到負值中的最大值。循環

相關文章
相關標籤/搜索