分配问题

来源:互联网 发布:淘宝客服有在家做的吗 编辑:程序博客网 时间:2024/04/30 09:32

有 n 件工作要分配给 n 个人做。第 i 个人做第 j件工作产生的效益为 cij。试设计一个将 n 件工作分配给 n 个人做的分配方案,使产生的总效益最大。

费用流裸题,跑一遍最大费用最大流,跑一遍最小费用最大流,比较裸。

#include<bits/stdc++.h>using namespace std;const int MAXN=2e5+5;const int INF=1e9;const int base=1e5;struct edge{    int u,to,next,w,c;}e[MAXN<<1],e2[MAXN<<1];int head[MAXN],cnt=1,head2[MAXN],cnt2=1;inline void add(int u,int v,int w,int cost){    e[++cnt]=(edge){u,v,head[u],w,cost},head[u]=cnt;    e2[++cnt2]=(edge){u,v,head2[u],w,cost},head2[u]=cnt2;}int dis[MAXN],pre[MAXN];bool vis[MAXN];int n,s,t;queue<int>q;bool SPFAMIN(int x){    memset(pre,0,sizeof(pre));    memset(vis,0,sizeof(vis));    for(int i=s;i<=t;i++)dis[i]=INF;    q.push(x);dis[x]=0;vis[x]=1;    while(q.size()){        int u=q.front();q.pop();vis[u]=0;        for(int i=head[u];i;i=e[i].next){            int v=e[i].to,w=e[i].c;            if(e[i].w){                if(dis[u]+w<dis[v]){                    dis[v]=dis[u]+w;pre[v]=i;                    if(!vis[v]){                        vis[v]=1;q.push(v);                    }                }            }        }    }    if(dis[t]==INF)return 0;    return 1;} int MCMIN(){    int cost=0;    while(SPFAMIN(s)){        int tem=INF;        for(int i=pre[t];i;i=pre[e[i].u]){            tem=min(tem,e[i].w);        }        for(int i=pre[t];i;i=pre[e[i].u]){            e[i].w-=tem;e[i^1].w+=tem;cost+=tem*e[i].c;        }     }    return cost; }bool SPFAMAX(int x){    memset(pre,0,sizeof(pre));    memset(vis,0,sizeof(vis));    for(int i=s;i<=t;i++)dis[i]=-INF;    q.push(x);dis[x]=0;vis[x]=1;    while(q.size()){        int u=q.front();q.pop();vis[u]=0;        for(int i=head2[u];i;i=e2[i].next){            int v=e2[i].to,w=e2[i].c;            if(e2[i].w){                if(dis[u]+w>dis[v]){                    dis[v]=dis[u]+w;pre[v]=i;                    if(!vis[v]){                        vis[v]=1;q.push(v);                    }                }            }        }    }    if(dis[t]==-INF)return 0;    return 1;} int MCMAX(){    int cost=0;    while(SPFAMAX(s)){        int tem=INF;        for(int i=pre[t];i;i=pre[e2[i].u]){            tem=min(tem,e2[i].w);        }        for(int i=pre[t];i;i=pre[e2[i].u]){            e2[i].w-=tem;e2[i^1].w+=tem;cost+=tem*e2[i].c;        }     }    return cost; }int main(){    int tem;    scanf("%d",&n);    s=0;t=n+base+1;    for(int i=1;i<=n;i++){        add(s,i,1,0),add(i,s,0,0);        add(i+base,t,1,0),add(t,i+base,0,0);        for(int j=1;j<=n;j++){            scanf("%d",&tem);            add(i,j+base,1,tem),add(j+base,i,0,-tem);        }    }    cout<<MCMIN()<<endl;    cout<<MCMAX()<<endl;    return 0;}