1. 程式人生 > 實用技巧 >P1559 運動員最佳匹配問題 KM演算法

P1559 運動員最佳匹配問題 KM演算法

題目描述

羽毛球隊有男女運動員各n人。給定2 個n×n矩陣P和Q。P[i][j]是男運動員i和女運動員j配對組成混合雙打的男運動員競賽優勢;Q[i][j]是女運動員i和男運動員j配合的女運動員競賽優勢。由於技術配合和心理狀態等各種因素影響,P[i][j]不一定等於Q[j][i]。男運動員i和女運動員j配對組成混合雙打的男女雙方競賽優勢為P[i][j]*Q[j][i]。設計一個演算法,計算男女運動員最佳配對法,使各組男女雙方競賽優勢的總和達到最大。

輸入格式

第一行有1 個正整數n (1≤n≤20)。接下來的2n行,每行n個數。前n行是p,後n行是q。

輸出格式

將計算出的男女雙方競賽優勢的總和的最大值輸出。

重新定義一個數組e【】【】來表示P【】【】Q【】【】的乘積

其餘部分就全部都是KM模板了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 //Data
 4 typedef long long ll;
 5 const int N=30;
 6 const int inf=0x3f3f3f3f;
 7 int n,e[N+7][N+7];
 8 int P[N][N],Q[N][N];
 9 //KM
10 int mb[N+7],vb[N+7],ka[N+7],kb[N+7],p[N+7],c[N+7];
11 int qf,qb,q[N+7
]; 12 void Bfs(int u){ 13 int a,v=0,vl=0,d; 14 for(int i=1;i<=n;i++) p[i]=0,c[i]=inf; 15 mb[v]=u; 16 do { 17 a=mb[v],d=inf,vb[v]=1; 18 for(int b=1;b<=n;b++)if(!vb[b]){ 19 if(c[b]>ka[a]+kb[b]-e[a][b]) 20 c[b]=ka[a]+kb[b]-e[a][b],p[b]=v;
21 if(c[b]<d) d=c[b],vl=b; 22 } 23 for(int b=0;b<=n;b++) 24 if(vb[b]) ka[mb[b]]-=d,kb[b]+=d; 25 else c[b]-=d; 26 v=vl; 27 } while(mb[v]); 28 while(v) mb[v]=mb[p[v]],v=p[v]; 29 } 30 ll KM() 31 { 32 for(int i=1;i<=n;i++) 33 mb[i]=ka[i]=kb[i]=0; 34 for(int a=1;a<=n;a++){ 35 for(int b=1;b<=n;b++) vb[b]=0; 36 Bfs(a); 37 } 38 ll res=0; 39 for(int b=1;b<=n;b++) res+=e[mb[b]][b]; 40 return res; 41 } 42 43 //Main 44 int main() 45 { 46 47 48 49 scanf("%d",&n); 50 for(int i=1;i<=n;i++) 51 for(int j=1;j<=n;j++){ 52 scanf("%d",&P[i][j]); 53 } 54 for(int i=1;i<=n;i++) 55 for(int j=1;j<=n;j++){ 56 scanf("%d",&Q[i][j]); 57 } 58 for(int i=1;i<=n;i++) 59 for(int j=1;j<=n;j++){ 60 e[i][j]=P[i][j]*Q[j][i]; 61 } 62 printf("%lld\n",KM()); 63 return 0; 64 }
View Code