POJ 2400 KM
http://poj.org/problem?id=2400
题意:N个领导对N个员工排名(排在最前面的分数为0,表示评价最高),同时N个员工对N个领导排名,原则同上
求 每个人平均分最少
题目输入足够把人绕晕。。。
还要求把所有的情况输出,用dfs找所有的情况 我做这个题为了熟悉KM
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#define Max(a,b)a>b?a:b
#define Min(a,b)a<b?a:b
#define MAX 18
#define inf 9999999
using namespace std;
int lx[MAX],ly[MAX],map[MAX][MAX],link[MAX];
bool vx[MAX],vy[MAX];
int n,m,ans,cnt;
bool dfs(int u)
{
int j;
vx[u]=1;
for(j=1;j<=m;j++)
if(!vy[j]&&map[u][j]==lx[u]+ly[j])//map[u][j]==vx[u]+vy[j]妹的!
{
vy[j]=1;
if(!link[j]||dfs(link[j]))
{
link[j]=u;
return true;
}
}
return false;
}
int KM()
{
int i,j,k,mi;
for(i=1;i<=n;i++)
for(lx[i]=-inf,j=1;j<=m;j++)
lx[i]=Max(lx[i],map[i][j]);
memset(ly,0,sizeof(ly));
memset(link,0,sizeof(link));
for(i=1;i<=n;i++)
{
while(1)
{ memset(vx,0,sizeof(vx));
memset(vy,0,sizeof(vy));
if(dfs(i))break;
mi=inf;
for(j=1;j<=n;j++)
if(vx[j])
for(k=1;k<=m;k++)
if(!vy[k])
mi=Min(mi,lx[j]+ly[k]-map[j][k]);
for(j=1;j<=n;j++)if(vx[j])lx[j]-=mi;
for(j=1;j<=m;j++)if(vy[j])ly[j]+=mi;
}
}
ans=0;
for(i=1;i<=m;i++)
if(link[i])ans-=map[link[i]][i];
return ans;
}
void OutDfs(int dep,int Sum)
{
int i;
if(Sum>ans)return ;
if(dep>n)
{
if(Sum!=ans)return ;
printf("Best Pairing %d\n",++cnt);
for(i=1;i<=m;i++)
printf("Supervisor %d with Employee %d\n",i,link[i]);
}
else
{
for(i=1;i<=m;i++)
if(!vy[i])
{
vy[i]=1;
link[dep]=i;//??
OutDfs(dep+1,Sum-map[dep][i]);
vy[i]=0;
}
}
}
int main()
{
int CASE,ca,i,j,k;
scanf("%d",&CASE);
for(ca=1;ca<=CASE;ca++)
{
memset(map,0,sizeof(map));
scanf("%d",&n);
m=n;
for(i=1;i<=n;i++)
for(j=0;j<m;j++)
{
scanf("%d",&k);
map[k][i]-=j;
}
for(i=1;i<=n;i++)
for(j=0;j<n;j++)
{
scanf("%d",&k);
map[i][k]-=j;
}
printf("Data Set %d, Best average difference: %.6f\n",ca,0.5*KM()/n);
cnt=0;
memset(vy,0,sizeof(vy));
OutDfs(1,0);
printf("\n");
}
return 0;
}

浙公网安备 33010602011771号