前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >洛谷P4014 分配问题(费用流)

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

作者头像
attack
发布2018-04-10 15:14:20
6840
发布2018-04-10 15:14:20
举报

题目描述

有 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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
5
14

说明

1 \leq n \leq 1001≤n≤100

一个人只能修一个工件

又是一道挺裸的费用流

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

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

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

代码语言:javascript
复制
#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;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-03-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述
  • 输入输出格式
  • 输入输出样例
  • 说明
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档