poj 2400 Supervisor, Supervisee

来源:互联网 发布:linux制作win7启动盘 编辑:程序博客网 时间:2024/05/01 21:29

Supervisor, Supervisee
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 2764 Accepted: 773

Description

Suppose some supervisors each get to hire a new person for their department. There are N people to be placed in these N departments. Each supervisor interviews all N people, and ranks them according to how much she wants each of them in her department (1 being "really want" and N being "really don't want"). In turn, each of the N candidates ranks each of the supervisors as to how much that person would like to work for that supervisor (again, 1 is "really want to work for him/her" and N is "really don't want to work for him/her"). Given the scores that each supervisor has for each candidate, and the scores each candidate has for each manager, write a computer program to determine the "best match" of candidates to supervisors. The "best match" is determined by finding the distribution that leads to the highest overall (i.e. sum of) satisfaction for all people. The closer a person is to her number one choice, the better. If everyone gets their number one choice, the average difference will be 0.

Input

The first line of the input will contain a single integer greater than 0 specifying the number of test cases. 

The next line will contain a single integer value N, 0 < N < 15, representing the number of supervisors (and the number of employees - there are N supervisors and N employees). The next N lines will be the preferences of each of the N supervisors. Each line will contain N integer entries (1 through N for employees 1 through N), each separated by a space character, that represents the preferences of that supervisor from most preferred to least preferred. More specifically, the first entry on the line will represent that supervisor's first choice, the second entry her second, and so on. The next N lines will be the preferences of the N employees, in the same format as the supervisors. 

All lines of data in the input file will end with an empty line.

Output

For each test case, write the test case number (starting with 1) followed by the best average difference written to six digits of precision to the right of the decimal point. On the next line, show which best match it was (starting with 1). On the next N lines, show each supervisor (starting with 1) followed by the employee with which she was matched (1 per line). NOTE: if there is more than one best match, matches should be listed in ascending permuted order (see sample output). 

Separate each data set with an empty line.

Sample Input

271 2 3 4 5 6 72 1 3 4 5 6 73 1 2 4 5 6 74 1 2 3 5 6 75 1 2 3 4 6 76 1 2 3 4 5 77 1 2 3 4 5 61 2 3 4 5 6 72 1 3 4 5 6 73 1 2 4 5 6 74 1 2 3 5 6 75 1 2 3 4 6 76 1 2 3 4 5 77 1 2 3 4 5 621 22 11 21 2

Sample Output

Data Set 1, Best average difference: 0.000000Best Pairing 1Supervisor 1 with Employee 1Supervisor 2 with Employee 2Supervisor 3 with Employee 3Supervisor 4 with Employee 4Supervisor 5 with Employee 5Supervisor 6 with Employee 6Supervisor 7 with Employee 7Data Set 2, Best average difference: 0.250000Best Pairing 1Supervisor 1 with Employee 1Supervisor 2 with Employee 2

大意:就是有n个老板和n个雇员,每个员工对n个老板自己心中都有一个排名,老板对每个员工也是,现在就是让你找出最符合期望的一个组合。就是每个人越看对方越舒服越好,这样的话就是尽量的安排位置最靠前的一个。

今天学习了km算法,就是专门解决类似的问题的,首先就是建造一个二分图,然后给他们加上一个权值,大小就是位置的列数。我们知道km算法求的是一个最大权,而在这里

相当于是求一个最小权了,那样的话直接权值全变成负的就可以了。

这样就可以求出一个最小权了,之后再去dfs求出所有可能的解就可以啦。

表示这个km算法,理解的不是特别到位,只是暂时的会用,套个板子知道他能干什么,像kmp这种似的。

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAXN=20;const int inf=1e9;int n,d,ans,cnt;int w[MAXN][MAXN],kx[MAXN],ky[MAXN],pre[MAXN];bool visx[MAXN],visy[MAXN];void init(){    memset(ky,0,sizeof(ky));    memset(pre,-1,sizeof(pre));    for(int i=1;i<=n;++i)    {        kx[i]=w[i][1];        for(int j=2;j<=n;++j)kx[i]=max(kx[i],w[i][j]);    }}bool dfs(int u){    visx[u]=1;    for(int i=1;i<=n;++i)    {        if(!visy[i])        {            int t=kx[u]+ky[i]-w[u][i];            if(!t)            {                visy[i]=1;                if(pre[i]==-1||dfs(pre[i]))                {                    pre[i]=u;                    return 1;                }            }            else d=min(d,t);        }    }    return 0;}int km(){    for(int i=1;i<=n;++i)    {        while(1)        {            memset(visx,0,sizeof(visx));            memset(visy,0,sizeof(visy));            d=inf;            if(dfs(i))break;            for(int j=1;j<=n;++j)            {                if(visx[j])kx[j]-=d;                if(visy[j])ky[j]+=d;            }        }    }    ans=0;    for(int i=1;i<=n;++i)    {        if(pre[i]!=-1)ans+=w[pre[i]][i];    }    return -ans;}//上面这些就是搜索最大权的了void dfs_path(int u,int sum){    if(sum<ans)return ;    if(u>n)    {        if(sum!=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]=1;                pre[u]=i;                dfs_path(u+1,sum+w[u][i]);                visx[i]=0;            }        }    }}int main(){    int i,j;    int t,x,ca=0;    scanf("%d",&t);    while(t--)    {        memset(w,0,sizeof(w));        scanf("%d",&n);        for(i=1;i<=n;++i)            for(j=1;j<=n;++j)        {            scanf("%d",&x);            w[x][i]+=1-j;        }        for(i=1;i<=n;++i)            for(j=1;j<=n;++j)        {            scanf("%d",&x);            w[i][x]+=1-j;        }        init();        printf("Data Set %d, Best average difference: %lf\n",++ca,km()*0.5/n);        memset(visx,0,sizeof(visx));        cnt=1;        dfs_path(1,0);        puts("");    }    return 0;}


0 0