欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

洛谷P4014 分配问题(费用流)

程序员文章站 2022-04-09 21:01:28
题目描述 有 nn 件工作要分配给 nn 个人做。第 ii 个人做第 jj 件工作产生的效益为 c_{ij}cij​ 。试设计一个将 nn 件工作分配给 nn 个人做的分配方案,使产生的总效益最大。 输入输出格式 输入格式: 文件的第 11 行有 11 个正整数 nn ,表示有 nn 件工作要分配给 ......

题目描述

有 nn 件工作要分配给 nn 个人做。第 ii 个人做第 jj 件工作产生的效益为 c_{ij}cij 。试设计一个将 nn 件工作分配给 nn 个人做的分配方案,使产生的总效益最大。

输入输出格式

输入格式:

 

文件的第 11 行有 11 个正整数 nn ,表示有 nn 件工作要分配给 nn 个人做。

接下来的 nn 行中,每行有 nn 个整数 c_{ij}cij ​​,表示第 ii 个人做第 jj 件工作产生的效益为 c_{ij}cij 。

 

输出格式:

 

两行分别输出最小总效益和最大总效益。

 

输入输出样例

输入样例#1: 复制
5
2 2 2 1 2
2 3 1 2 4
2 0 1 1 1
2 3 4 3 3
3 2 1 2 1
输出样例#1: 复制
5
14

说明

1 \leq n \leq 1001n100

一个人只能修一个工件

 

 

又是一道挺裸的费用流

从S向每个工人连容量为1,费用为0的边

从每个工件向T连容量为1,费用为0的边

从每个工人向每个工件连容量为1,费用为c[i][j]的边

 

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define AddEdge(x,y,z,f) add_edge(x,y,z,f),add_edge(y,x,-z,0)
using namespace std;
const int INF=1e8+10;
const int MAXN=1e4+10;
int N,M,S,T;
int C[MAXN][MAXN];
struct node
{
    int u,v,w,f,nxt;
}edge[MAXN];
int head[MAXN],num=2;
inline void add_edge(int x,int y,int z,int f)
{
    edge[num].u=x;
    edge[num].v=y;
    edge[num].w=z;
    edge[num].f=f;
    edge[num].nxt=head[x];
    head[x]=num++;
}
int dis[MAXN],vis[MAXN],Pre[MAXN];
bool SPFA()
{
    memset(dis,0xf,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue<int>q;
    q.push(S);
    dis[S]=0;
    while(q.size()!=0)
    {
        int p=q.front();q.pop();
        vis[p]=0;
        for(int i=head[p];i!=-1;i=edge[i].nxt)
        {
            if(edge[i].f&&dis[edge[i].v]>dis[p]+edge[i].w)
            {
                dis[edge[i].v]=dis[p]+edge[i].w;
                Pre[edge[i].v]=i;
                if(!vis[edge[i].v])
                    vis[edge[i].v]=1,q.push(edge[i].v);
            }
        }
    }
    return dis[T]<INF;
}
int F()
{
    int nowflow=INF;
    for(int now=T;now!=S;now=edge[Pre[now]].u)
        nowflow=min(nowflow,edge[Pre[now]].f);
    for(int now=T;now!=S;now=edge[Pre[now]].u)
        edge[Pre[now]].f-=nowflow,
        edge[Pre[now]^1].f+=nowflow;
    return nowflow*dis[T];
}
void MCMF()
{
    int ans=0;
    while(SPFA())
        ans+=F();
    printf("%d\n",abs(ans));
}
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #endif
    memset(head,-1,sizeof(head));
    scanf("%d",&N);
    S=0;T=N<<1|1;
    for(int i=1;i<=N;i++)
        for(int j=1;j<=N;j++)
            scanf("%d",&C[i][j]);
    for(int i=1;i<=N;i++)
        for(int j=1;j<=N;j++)
            AddEdge(i,j+N,C[i][j],1);
    for(int i=1;i<=N;i++)
        AddEdge(S,i,0,1),AddEdge(i+N,T,0,1);
    MCMF();
    memset(head,-1,sizeof(head));
    num=2;
    for(int i=1;i<=N;i++)
        for(int j=1;j<=N;j++)
            AddEdge(i,j+N,-C[i][j],1);
    for(int i=1;i<=N;i++)
        AddEdge(S,i,0,1),AddEdge(i+N,T,0,1);
    MCMF();
    return 0;
}