分配问题

来源:互联网 发布:网络头像男生 编辑:程序博客网 时间:2024/04/30 08:34

本题n个工作分给n个人,求最优,最差方案,所以是KM算法。当然也可以用费用流建模。

建模方法如下:

建立源点ST和汇点ED,由ST向n个工作连费用为0,流量为1的边,由每个人向ED连费用为0,流量为1的边,由n个工作向n个人连流量为无穷大,费用为wij的边,最后跑一遍最小费用最大流和最大费用最大流即可。

代码如下:

#include <iostream>#include <algorithm>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <vector>#include <queue>#define M 1001011#define INF 0x7fffffff/3#define ST 2001#define ED 2002using namespace std;int n,m;int num=0;int ans=0;int p[M];int fmap[201][201];int cost[M],flag[M],pre[M];int q[4*M];struct node{    int a;    int b;    int w;    int f;    int next;}str1[M];void init(){    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            int x;            scanf("%d",&x);            fmap[i][j]=x;        }    }}void add(int x,int y,int z,int fl){    str1[num].a=x;    str1[num].b=y;    str1[num].w=z;    str1[num].f=fl;    str1[num].next=p[x];    p[x]=num++;    swap(x,y);    str1[num].a=x;    str1[num].b=y;    str1[num].w=-z;    str1[num].f=0;    str1[num].next=p[x];    p[x]=num++;}bool spfa(int src){    memset(flag,0,sizeof(flag));    for(int i=0;i<=ED;i++)        cost[i]=INF;    cost[src]=0;    pre[src]=-1;    flag[src]=1;    int l=0,r=0;    q[r++]=src;    while(l<r)    {        int k=q[l++];        flag[k]=0;        for(int i=p[k];i!=-1;i=str1[i].next)        {            int v=str1[i].b;            if(cost[v]>cost[k]+str1[i].w&&str1[i].f>0)            {                cost[v]=cost[k]+str1[i].w;                pre[v]=i;                if(!flag[v])                {                    flag[v]=1;                    q[r++]=v;                }            }        }    }    if(cost[ED]==INF)        return false;    return true;}void start(){    int minx=INF;    for(int i=pre[ED];i!=-1;i=pre[str1[i^1].b])        minx=min(minx,str1[i].f);    for(int i=pre[ED];i!=-1;i=pre[str1[i^1].b])    {        str1[i].f-=minx;        str1[i^1].f+=minx;    }    ans+=cost[ED]*minx;}void spfaflow(){    ans=0;    while(spfa(ST))        start();}void start1(){    num=0;    memset(p,-1,sizeof(p));    for(int i=1;i<=n;i++)        add(ST,i,0,1);    for(int i=1;i<=n;i++)        add(i+n,ED,0,1);    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            add(i,j+n,fmap[i][j],INF);        }    }    spfaflow();    printf("%d\n",ans);}void start2(){    num=0;    memset(p,-1,sizeof(p));    for(int i=1;i<=n;i++)        add(ST,i,0,1);    for(int i=1;i<=n;i++)        add(i+n,ED,0,1);    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            add(i,j+n,-fmap[i][j],INF);        }    }    spfaflow();    printf("%d\n",-ans);}int main(){    freopen("T18.in","r",stdin);    freopen("T18.out","w",stdout);    init();    start1();    start2();    return 0;}

0 0