您的位置:首页 > 其它

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来表示)。

代码:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: