• 洛谷——P4014 分配问题


    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和超级汇点T,超级源点向每个工人连边,容量为1,费用为0,表示限制每个人只能有一种工作;  

    每个工人向每个工作连边,容量为1,费用为0,这样当这条边有流时 ,费用即为收益;

    每个工作向超级汇点连边 ,容量为1,费用为0 ,表示限制每个工作只能被做一次;

    跑完最大流后收益即为最小收益。

    最大收益,即最大费用流 ,将原图中的边的费用全部取反 ,然后跑费用流 ,最后费用取反即可

    我的代码自带大常数QWQ

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    
    #define N 1010100
    using namespace std;
    
    int n,m,S,T,head[N],tot;
    struct node{
        int to,next,flow,w;
    }e[N];
    
    int dis[N],flow[N],pre[N],last[N],cost;
    bool vis[N];
    
    queue<int>Q;
    struct MCMFF{
        void init(){
            tot=-1,cost=0;
            memset(head,-1,sizeof(head));
            memset(e,0,sizeof(e));
        }
        void add(int u,int v,int flow,int w){
            e[++tot].to=v,e[tot].next=head[u],head[u]=tot,e[tot].w=w,e[tot].flow=flow;
        }
        void Add(int u,int v,int flow,int w){
            add(u,v,flow,w);
            add(v,u,0,-w);
        }
        bool spfa()
        {
            memset(vis,0,sizeof(vis));
            memset(dis,0x7f,sizeof(dis));
            memset(flow,0x7f,sizeof(flow));
            Q.push(S);vis[S]=1,pre[T]=-1,dis[S]=0;
            while(!Q.empty()){
                int u=Q.front();Q.pop();
                vis[u]=0;
                for(int i=head[u];i!=-1;i=e[i].next){
                    int v=e[i].to;
                    if(e[i].flow>0&&dis[v]>dis[u]+e[i].w){
                        dis[v]=dis[u]+e[i].w;
                        pre[v]=u,last[v]=i;
                        flow[v]=min(flow[v],e[i].flow);
                        if(!vis[v]){
                            Q.push(v);
                            vis[v]=1;
                        }
                    }
                }
            }return pre[T]!=-1;
        }
        void MCMF(){
            while(spfa()){
                int u=T;
                cost+=flow[T]*dis[T];
                while(u!=S){
                    e[last[u]].flow-=flow[T];
                    e[last[u]^1].flow+=flow[T];
                    u=pre[u];
                }
            }
        }
    }netfl;
    
    int work[105][105];
    
    int main()
    {
        scanf("%d",&n);
        netfl.init();
        S=0,T=2*n+1;
        for(int i=1;i<=n;i++){
            netfl.Add(S,i,1,0);
            netfl.Add(i+n,T,1,0);
            for(int j=1;j<=n;j++){
                scanf("%d",&work[i][j]);
                netfl.Add(i,j+n,1,work[i][j]);
            }
        }
        netfl.MCMF();
        printf("%d
    ",cost);
        netfl.init();
        for(int i=1;i<=n;i++){
            netfl.Add(S,i,1,0);
            netfl.Add(i+n,T,1,0); 
            for(int j=1;j<=n;j++){
                netfl.Add(i,j+n,1,-1*work[i][j]);
            }
        }
        netfl.MCMF();
        printf("%d
    ",-1*cost);
        return 0;
    }
  • 相关阅读:
    java基础知识回顾之---java String final类构造方法
    java基础知识回顾之---java String final类普通方法
    递归的理解
    跟着牛人学习
    【轻松学排序算法】眼睛直观感受几种常用排序算法
    《PhotoShop CS6 》第一节 矢量与分辨率
    SQL 查询当天,本月,本周的记录
    SQL创建表脚本
    varchar和Nvarchar区别
    [C#] 我的log4net使用手册
  • 原文地址:https://www.cnblogs.com/song-/p/9549988.html
Copyright © 2020-2023  润新知