带权的最佳匹配,讲两个矩阵的喜好值相加,用大数减去每条边的权值,求最小权值匹配 代码: #include<iostream> using namespace std; #define MAX 40 #define inf 1000000 int vl[MAX],vr[MAX],slack[MAX],link[MAX],a[MAX],b[MAX]; int w[MAX][MAX],res[MAX],v[MAX]; int n,ans,pairs; void dfs(int i,int total) { int j; if(i==n) { if(total==ans) { printf("Best Pairing %d/n",++pairs); for(j=0;j<n;j++) { printf("Supervisor %d with Employee %d/n",j+1,res[j]+1); } } return; } if(total>ans) { return; } for(j=0;j<n;j++) { if(!v[j]) { v[j]=1; res[i]=j; dfs(i+1,total+w[i][j]); v[j]=0; } } return ; } bool find(int i) { int j,val; vl[i]=1;//Xi进入交错树 for(j=0;j<n;j++) { if(vr[j])//Yj已经被需求 { continue; } val=a[i]+b[j]-w[i][j]; if(val==0)//边i->j在生成子图中 { vr[j]=1;//Yj进入交错树 if(link[j]==-1||find(link[j])) { link[j]=i; return true; } } else { if(slack[j]>val)//更新slack的值 slack[j]=val; } } return false; } void KM() { int i,j,d; memset(link,-1,sizeof(link)); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); for(i=0;i<n;i++)//初始化顶标 { for(j=0;j<n;j++) { if(w[i][j]>a[i]) a[i]=w[i][j]; } } for(i=0;i<n;i++) { for(j=0;j<n;j++) slack[j]=inf; while(true) { memset(vl,0,sizeof(vl)); memset(vr,0,sizeof(vr)); if(find(i)) { break; } d=inf; for(j=0;j<n;j++) { if(!vr[j]&&d>slack[j]) d=slack[j]; } for(j=0;j<n;j++) { if(vl[j])//Xj在交错树中 a[j]-=d; } for(j=0;j<n;j++) { if(vr[j])//Yj在交错树中 { b[j]+=d; } else { slack[j]-=d; } } } } ans=0; for(i=0;i<n;i++) { if(link[i]!=-1) ans+=w[link[i]][i]; } } int main() { int i,j,test,t,cnt; scanf("%d",&test); for(cnt=1;cnt<=test;cnt++) { memset(w,0,sizeof(w)); scanf("%d",&n); for(i=0;i<n;i++) { for(j=0;j<n;j++) { scanf("%d",&t); w[--t][i]=j; } } for(i=0;i<n;i++) { for(j=0;j<n;j++) { scanf("%d",&t); w[i][--t]+=j; } } for(i=0;i<n;i++) { for(j=0;j<n;j++) { w[i][j]=inf-w[i][j]; } } KM(); ans=n*inf-ans; for(i=0;i<n;i++) { for(j=0;j<n;j++) { w[i][j]=inf-w[i][j]; } } printf("Data Set %d, Best average difference: %.6lf/n",cnt,double(ans)/(2*n)); memset(v,0,sizeof(v)); memset(res,0,sizeof(res)); pairs=0; dfs(0,0); printf("/n"); } return 0; }