您的位置:首页 > 其它

POJ 2400 Supervisor, Supervisee

2014-02-14 15:46 211 查看
二分图最优匹配第二题,KM算法。

题目大意:

一共有N个管理者和N个雇员,每个雇员会跟随一个管理者。每个雇员会对管理者的喜好程度进行排名,管理者也同样会对雇员进行排名,问如何对管理者和雇员进行配对使总排名的平均值最小。

解题思路:

KM算法求最小权的匹配。

下面是代码:

#include <stdio.h>
#include <string.h>
const int inf=1<<30;
int w[20][20],n,km1[20],km2[20],d,pre[20],cnt,ans;
bool visx[20],visy[20];
void init()
{
memset(km2,0,sizeof(km2));
memset(pre,-1,sizeof(pre));
for(int i=1; i<=n; i++)
{
km1[i]=w[i][1];
for(int j=2; j<=n; j++)
{
if(km1[i]<w[i][j])km1[i]=w[i][j];
}
}
}
bool dfs(int src)
{
visx[src]=true;
for(int i=1; i<=n; i++)
{
if(!visy[i])
{
int t=km1[src]+km2[i]-w[src][i];
if(!t)
{
visy[i]=true;
if(pre[i]==-1||dfs(pre[i]))
{
pre[i]=src;
return true;
}
}
else if(d>t)d=t;
}
}
return false;
}
int km()
{
for(int i=1; i<=n; i++)
{
while(1)
{
memset(visx,false,sizeof(visx));
memset(visy,false,sizeof(visy));
d=inf;
if(dfs(i))break;
for(int j=1; j<=n; j++)
{
if(visx[j])km1[j]-=d;
if(visy[j])km2[j]+=d;
}
}
}
ans=0;
for(int i=1; i<=n; i++)
{
if(pre[i]!=-1)ans+=w[pre[i]][i];
}
return -ans;
}
void dfs(int src,int ca)
{
if(ca<ans)return;
if(src>n)
{
if(ca!=ans)return;
printf("Best Pairing %d\n",cnt++);
for(int i=1; i<=n; i++)
{
printf("Supervisor %d with Employee %d\n",i,pre[i]);
}
}
else
{
for(int i=1; i<=n; i++)
{
if(!visx[i])
{
visx[i]=true;
pre[src]=i;
dfs(src+1,ca+w[src][i]);
visx[i]=false;
}
}
}
}
int main()
{
int t,x,case1=1;
scanf("%d\n",&t);
while(t--)
{
scanf("%d\n",&n);
memset(w,0,sizeof(w));
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d",&x);
w[x][i]-=(j-1);
}
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d",&x);
w[i][x]-=(j-1);
}
}
init();
printf("Data Set %d, Best average difference: %lf\n",case1++,(km()*0.5)/n);
memset(visx,0,sizeof(visx));
cnt=1;
dfs(1,0);
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: