POJ 2400 Supervisor, Supervisee

来源:互联网 发布:淘宝上买港版iphone6s 编辑:程序博客网 时间:2024/04/27 23:04

二分图最优匹配第二题,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;}


1 0
原创粉丝点击