您的位置:首页 > 其它

POJ-2400 Supervisor, Supervisee 最小权匹配

2012-11-21 19:46 267 查看
  题目链接:http://poj.org/problem?id=2400

  话说光理解题意就搞了很久啊,说说题意吧:公司有n个管理者要招聘n个员工,所以每个管理者对每个员工进行面试,然后管理者和员工相互做出评价,每个管理者要对每个员工打分,同样每个员工要对每个管理者打分,分数越低评价越高,分数范围0,n-1。题目要求你对管理者和员工进行配对,要求所有配对的管理者和员工的分数之和最小,并且输出所有的情况。

  这个题目的难点就是要求所有的情况,我一开始想的就是枚举全排列做了,但看到数据量n<15,枚举是O(n!),如果数据恶心点,那么也会超时!想了一天,实在是没有其他的方法啊!其实n<15也已经暗示了要枚举做的啊!DFS试试,果然63ms就A了!看来以后还得把题目看得透一点!回想自己做区预赛的题目,每次也是遇到时间复杂度理论上限铁定会超时的时候,都不敢动手,但赛后发现,其实很多是可以搞的,所以经验还有待加强啊! PS:这题数据是反的= =。

//STATUS:G++_AC_63MS_716KB
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define LL long long
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int MAX=20,INF=200000000;

int w[MAX][MAX],S[MAX],T[MAX],lx[MAX],ly[MAX],A[MAX],y[MAX],vis[MAX];
int Tu,n,ans,anscou,slack;

int match(int u)
{
int v,t;
S[u]=1;
for(v=1;v<=n;v++){
t=w[u][v]-lx[u]-ly[v];
if(!t){
if(!T[v]){
T[v]=1;
if(!y[v] || match(y[v])){
y[v]=u;
return 1;
}
}
}
else if(t<slack)slack=t;
}
return 0;
}

void KM()
{
int i,j,a;
mem(ly,0);
for(i=1;i<=n;i++){
lx[i]=w[i][1];
for(j=2;j<=n;j++)
if(w[i][j]<lx[i])lx[i]=w[i][j];
}
for(i=1;i<=n;i++){
while(1){
slack=INF;
mem(S,0);mem(T,0);
if(match(i))break;
for(j=1;j<=n;j++){
if(S[j])lx[j]+=slack;
if(T[j])ly[j]-=slack;
}
}
}
}

void dfs(int cur,int s)
{
if(s>ans || (cur==n+1 && s!=ans))return ;
int i;
if(cur==n+1){
printf("Best Pairing %d\n",anscou++);
for(i=1;i<=n;i++)
printf("Supervisor %d with Employee %d\n",i,A[i]);
return ;
}
for(i=1;i<=n;i++){
if(!vis[i]){
vis[i]=1;
A[cur]=i;
dfs(cur+1,s+w[cur][i]);
vis[i]=0;
}
}
}

int main()
{
//   freopen("in.txt","r",stdin);
int i,j,t,k=1;
scanf("%d",&Tu);
while(Tu--)
{
mem(y,0);
scanf("%d",&n);
for(i=1;i<=n;i++){
for(j=0;j<n;j++){
scanf("%d",&t);
w[t][i]=j;
}
}
for(i=1;i<=n;i++){
for(j=0;j<n;j++){
scanf("%d",&t);
w[i][t]+=j;
}
}

KM();

for(ans=0,i=1;i<=n;i++)
ans+=w[y[i]][i];
printf("Data Set %d, Best average difference: %.6f\n",k++,ans*0.5/n);
anscou=1;
mem(vis,0);
dfs(1,0);
if(Tu)putchar('\n');
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: