题意:给出雇主对雇员的满意度和雇员对雇主的满意度,分数越低代表评价越高,求给出最优匹配方案。当有多种最优匹配,全部输出!
思路:典型的最小权匹配,km算法求解
View Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define inf 0x3f3f3f3f 7 #define N 111 8 int net[N][N],x[N],y[N],lx[N],ly[N],link[N],b[N],like[N]; 9 int n,sum,d,cnt; 10 bool km_dfs(int u) 11 { 12 x[u]=1; 13 for(int i=1;i<=n;i++) 14 { 15 if(y[i])continue; 16 int t=lx[u]+ly[i]-net[u][i]; 17 if(t==0) 18 { 19 y[i]=1; 20 if(!link[i]||km_dfs(link[i])) 21 { 22 link[i]=u; 23 return true; 24 } 25 } 26 else d=min(d,t); 27 } 28 return false; 29 } 30 double km() 31 { 32 memset(lx,0,sizeof(lx)); 33 memset(ly,0,sizeof(ly)); 34 memset(link,0,sizeof(link)); 35 for(int i=1;i<=n;i++) 36 { 37 while(1){ 38 d=inf; 39 memset(x,0,sizeof(x)); 40 memset(y,0,sizeof(y)); 41 if(km_dfs(i))break; 42 for(int j=1;j<=n;j++) 43 { 44 if(x[j])lx[j]-=d; 45 if(y[j])ly[j]+=d; 46 } 47 } 48 } 49 sum=0; 50 for(int i=1;i<=n;i++) 51 { 52 sum-=lx[i]+ly[i]; 53 } 54 return 1.0*sum/(n*2); 55 } 56 void dfs(int step,int total) 57 { 58 if(total>sum)return ; 59 if(step==n+1) 60 { 61 printf("Best Pairing %d\n",cnt++); 62 for(int i=1;i<=n;i++) 63 printf("Supervisor %d with Employee %d\n",i,like[i]); 64 return ; 65 } 66 for(int i=1;i<=n;i++) 67 { 68 if(!b[i]){ 69 b[i]=1; 70 like[step]=i; 71 dfs(step+1,total-net[step][i]); 72 b[i]=0; 73 } 74 } 75 } 76 int main() 77 { 78 int ca; 79 scanf("%d",&ca); 80 int cas=1; 81 while(ca--) 82 { 83 int x; 84 cnt=1; 85 memset(net,0,sizeof(net)); 86 scanf("%d",&n); 87 for(int i=1;i<=n;i++) 88 { 89 for(int j=1;j<=n;j++) 90 { 91 scanf("%d",&x); 92 net[x][i]-=j; 93 } 94 } 95 for(int i=1;i<=n;i++) 96 { 97 for(int j=1;j<=n;j++) 98 { 99 scanf("%d",&x); 100 net[i][x]-=j;//最小权匹配取负数 101 } 102 } 103 double ans=km(); 104 printf("Data Set %d, Best average difference: %.6lf\n",cas++,ans-1); 105 memset(b,0,sizeof(b)); 106 dfs(1,0); 107 printf("\n"); 108 } 109 return 0; 110 }