poj 2400 Supervisor, Supervisee 二分匹配 最小权完美匹配 KM算法
2012-07-23 14:18
417 查看
题意:有n个应聘者应聘n个部门,每个部门的经理对每个人的喜欢程度不一样(记1~N,最喜欢的为1),每个应聘者对每个经理的喜欢程度也不一样(同上)。给出每个经 理对应聘者的喜欢程度和应聘者对经理的喜欢程度,求平均最小偏差(貌似题目给出的两个矩阵是反的,有点不清晰啊)
思路:此题求最小权的完美匹配,cv[i][j]记录i候选人对j经理的喜爱程度,sv[i][j]记录i经理对j候选人的喜爱程度。w[i][j]表示i匹配j的偏差:-(sv[j][i]+cv[i][j]-2)(注:这里用KM算法求最小权,则w=-w或者可以用large-w来表示)。
代码:
思路:此题求最小权的完美匹配,cv[i][j]记录i候选人对j经理的喜爱程度,sv[i][j]记录i经理对j候选人的喜爱程度。w[i][j]表示i匹配j的偏差:-(sv[j][i]+cv[i][j]-2)(注:这里用KM算法求最小权,则w=-w或者可以用large-w来表示)。
代码:
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<queue> #include<vector> #define maxn 20 #define INF 0x3f3f3f3f #define clr(a,b) memset(a,b,sizeof(a)) #define max(a,b) a>b?a:b #define min(a,b) a<b?a:b using namespace std; bool ms; int sx[maxn],sy[maxn],w[maxn][maxn],mat[maxn],vis[maxn]; int g[maxn][maxn],lx[maxn],ly[maxn],sv[maxn][maxn],cv[maxn][maxn]; int n,ca; int cas=1,c,ans,q; void init() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) w[i][j]=-(sv[j][i]+cv[i][j]-2); } bool find(int x) { sx[x]=1; for(int i=1;i<=n;i++) { if(!sy[i]&&lx[x]+ly[i]==w[x][i]) { sy[i]=1; if(mat[i]==-1||find(mat[i])) { mat[i]=x; return 1; } } } return 0; } int KM() { int sum=0; for(int i=1;i<=n;i++) { ly[i]=0; lx[i]=-INF; for(int j=1;j<=n;j++) lx[i]=max(lx[i],w[i][j]); } clr(mat,-1); for(int i=1;i<=n;i++) while(1) { clr(sx,0); clr(sy,0); if(find(i)) break; int d=INF; for(int i=1;i<=n;i++) { if(sx[i]) { for(int j=1;j<=n;j++) { if(!sy[j]) d=min(lx[i]+ly[j]-w[i][j],d); } } } for(int i=1;i<=n;i++) { if(sx[i]) lx[i]-=d; if(sy[i]) ly[i]+=d; } } for(int i=1;i<=n;i++) sum+=w[mat[i]][i]; return -sum; } void dfs(int id,int s) { if(s>ans) return ; if(id==n+1) { printf("Best Pairing %d\n",q++); for(int i=1;i<=n;i++) printf("Supervisor %d with Employee %d\n",i,mat[i]); } else { for(int j=1;j<=n;j++) { if(!vis[j]) { vis[j]=1; mat[id]=j; dfs(id+1,s-w[mat[id]][id]); vis[j]=0; } } } } int main() { scanf("%d",&ca); while(ca--) { scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&c); cv[i][c]=j; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&c); sv[i][c]=j; } init(); q=1; ans=KM(); printf("Data Set %d, Best average difference: %lf\n",cas++,ans/(2.0*n)); clr(vis,0); dfs(1,0); puts(""); } return 0; }
相关文章推荐
- POJ-2400 Supervisor, Supervisee 最小权匹配
- 【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)
- 【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)
- poj 3686 The Windy's 二分匹配 KM算法求最小权匹配
- POJ 2400 KM算法 最小权匹配 回溯输出所有最优匹配方案
- POJ-2400 Supervisor, Supervisee 带权值匹配+枚举所有匹配情况
- POJ 2400 Supervisor, Supervisee(KM+DFS找相同最佳匹配)
- POJ 2400 Supervisor, Supervisee (二分图最大权匹配)
- POJ 2400 最小权匹配
- POJ 3020 Antenna Placement【二分匹配——最小路径覆盖】
- POJ 2400 KM最小权匹配+输出所有匹配方案
- poj 2195 二分匹配KM算法
- POJ 2400 Supervisor, Supervisee
- [ACM] POJ 3686 The Windy's (二分图最小权匹配,KM算法,特殊建图)
- POJ 1325 简单基础匈牙利二分匹配:最小点覆盖
- POJ 1422 二分匹配 最小路径覆盖(邻接表实现)
- poj 2400(最小权匹配)
- POJ 2400 Supervisor, Supervisee
- POJ 3041 匈牙利算法 最小覆盖 最大二分匹配
- POJ 2400 Supervisor, Supervisee