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

题目描述

有 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
#include
#include
#include
#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;
}

 

你可能感兴趣的:(洛谷P4014 分配问题(费用流))