pku2400 Supervisor, Supervisee 二分图最优匹配的全部解
题意:给出职工对经理的评分和经理对职工的评分。求出所有的匹配方案,使得平均满意度最高
解法:
KM匹配出最优解后,根据标号遍历得所有解。注意,调整顶标以后合法匹配边仍然是l[i]+r[j]=val[i][j]
代码:
Source Code
Problem: 2400 | User: yzhw | |
Memory: 408K | Time: 0MS | |
Language: G++ | Result: Accepted |
- Source Code
# include <cstdio> # include <cstring> # include <cstdlib> using namespace std; # define max(a,b) ((a)>(b)?(a):(b)) # define min(a,b) ((a)<(b)?(a):(b)) # define N 15 int map[N][N],match[N],ln[N],rn[N],n,c; bool l[N],r[N]; bool dfs(int pos) { //if(l[pos]) return false; l[pos]=true; for(int i=0;i<n;i++) if(!r[i]&&ln[pos]+rn[i]==map[pos][i]) { r[i]=true; if(match[i]==-1||dfs(match[i])) { match[i]=pos; return true; } } return false; } void adjust() { int minnum=0xfffffff; for(int i=0;i<n;i++) if(l[i]) for(int j=0;j<n;j++) if(!r[j]) minnum=min(minnum,ln[i]+rn[j]-map[i][j]); for(int i=0;i<n;i++) { if(l[i]) ln[i]-=minnum; if(r[i]) rn[i]+=minnum; } } void search(int now) { if(now==n) { int ret[N]; for(int i=0;i<n;i++) ret[match[i]]=i; printf("Best Pairing %d\n",++c); for(int i=0;i<n;i++) printf("Supervisor %d with Employee %d\n",i+1,ret[i]+1); //system("pause"); } for(int i=0;i<n;i++) if(match[i]==-1&&ln[now]+rn[i]==map[now][i]) { match[i]=now; search(now+1); match[i]=-1; } } int main() { int test; scanf("%d",&test); for(int tt=1;tt<=test;tt++) { scanf("%d",&n); memset(map,0,sizeof(map)); for(int i=0;i<n;i++) for(int j=0;j<n;j++) { int t; scanf("%d",&t); map[t-1][i]-=j; } for(int i=0;i<n;i++) for(int j=0;j<n;j++) { int t; scanf("%d",&t); map[i][t-1]-=j; } memset(match,-1,sizeof(match)); memset(rn,0,sizeof(rn)); for(int i=0;i<n;i++) { int maxnum=-0xfffffff; for(int j=0;j<n;j++) maxnum=max(maxnum,map[i][j]); ln[i]=maxnum; } double ans=0; for(int i=0;i<n;i++) { memset(l,false,sizeof(l)); memset(r,false,sizeof(r)); while(!dfs(i)) { adjust(); memset(l,false,sizeof(l)); memset(r,false,sizeof(r)); } } for(int i=0;i<n;i++) ans-=map[match[i]][i]; printf("Data Set %d, Best average difference: %.6f\n",tt,ans/n/2.0); memset(match,-1,sizeof(match)); c=0; search(0); printf("\n"); } return 0; }