KM算法详解+模板 - wenr - 博客园 http://www.cnblogs.com/wenruo/p/5264235.html
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 7 #define MAXN 305 8 #define inf 65553566 9 int love[MAXN][MAXN]; /// 记录每个妹子和每个男生的好感度 10 int ex_girl[MAXN]; /// 每个妹子的期望值 11 int ex_boy[MAXN]; /// 每个男生的期望值 12 bool vis_girl[MAXN]; /// 记录每一轮匹配匹配过的女生 13 bool vis_boy[MAXN]; /// 记录每一轮匹配匹配过的男生 14 int match[MAXN]; /// 记录每个男生匹配到的妹子 如果没有则为-1 15 int slack[MAXN]; /// 记录每个汉子如果能被妹子倾心最少还需要多少期望值 16 17 int n,sum; 18 19 ///为女孩找匹配的男孩 20 int find(int girl) 21 { 22 vis_girl[girl]=1; 23 for(int boy=1;boy<=n;boy++) 24 { 25 if(vis_boy[boy]) continue;///如果男孩已经被标记过,则找下一个 26 int gap=ex_girl[girl]+ex_boy[boy]-love[girl][boy];///看差距 27 if(gap==0) 28 { 29 vis_boy[boy]=1; 30 if(match[boy]==-1||find(match[boy]))///如果男孩未匹配过或者该男孩的妹子可以找其他人 31 { 32 match[boy]=girl;///将女孩匹配给男 33 return 1; 34 } 35 } 36 else 37 { 38 slack[boy]=min(slack[boy],gap); 39 } 40 } 41 return 0; 42 } 43 void KM() 44 { 45 memset(match,-1,sizeof(match)); 46 memset(ex_boy,0,sizeof(ex_boy)); 47 48 ///每个女生的初始期望值是与他相连的男生最大的好感度 49 for(int i=1;i<=n;i++) 50 { 51 ex_girl[i]=love[i][1]; 52 for(int j=2;j<=n;j++) 53 { 54 ex_girl[i]=max(ex_girl[i],love[i][j]); 55 } 56 } 57 ///尝试为每个女孩匹配男孩 58 for(int i=1;i<=n;i++) 59 { 60 fill(slack+1,slack+n+1,inf); 61 while(1) 62 { 63 64 /// 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止 65 ///记录每轮匹配中南海女孩是否被尝试匹配过 66 memset(vis_girl,0,sizeof(vis_girl)); 67 memset(vis_boy,0,sizeof(vis_boy)); 68 if(find(i)) break;///如果发现该女孩已经找到归宿,就进行下一个女孩 69 int d=inf; 70 for(int j=1;j<=n;j++) 71 if(!vis_boy[j])///看该男孩如果没有匹配的,就将最小的期望值给他 72 d=min(d,slack[j]); 73 74 for(int j=1;j<=n;j++) 75 { 76 if(vis_girl[j])///如果女孩已经匹配,则女孩的期望值减去 77 ex_girl[j]-=d; 78 if(vis_boy[j]) 79 ex_boy[j]+=d; 80 } 81 } 82 } 83 } 84 int main() 85 { 86 while(scanf("%d",&n)!=EOF) 87 { 88 sum=0; 89 for(int i=1;i<=n;i++) 90 for(int j=1;j<=n;j++) 91 { 92 scanf("%d",&love[i][j]); 93 } 94 KM(); 95 for(int i=1;i<=n;i++) 96 { 97 sum+=love[match[i]][i]; 98 } 99 printf("%d ",sum); 100 } 101 102 }