zoukankan      html  css  js  c++  java
  • 网络流二十四题 分配问题

    分配问题

    题目描述

    有 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

    说明

    1n100

    一个人只能修一个工件



    2018.7.5测试T3

    当时打出了最小费用,却没敢做,打了10分的搜索暴力(;′⌒`)

    其实挺简单的

    二分图,左边是人,右边的工作,

    建立一个超级源点,一个超级汇点

    建的边流量都是1(一个人只能修一个工件)

    与源点或汇点相连的费用全是0

    人与工作之间的费用是他们之间的效益

    一个最大一个最小,取反一下就可以辣

     1 #include <iostream>
     2 #include <queue>
     3 #include <cstring>
     4 #include <cstdio>
     5 #define inf 0x3f3f3f3f
     6 using namespace std;
     7 
     8 int n,s,t;
     9 int a[101][101];
    10 struct node{
    11     int u,v,flow,spend,next;
    12 }e[100100];
    13 int head[100100],tot=1;
    14 int from[100100],vis[100100],dis[100100];
    15 int ans;
    16 
    17 void add_node(int a,int b,int f,int s) {
    18     e[++tot]=(node){a,b,f,s,head[a]};
    19     head[a]=tot;
    20 }
    21 bool SPFA() {
    22     memset(dis,inf,sizeof(dis));
    23     memset(vis,0,sizeof(vis));
    24     queue<int> q;
    25     q.push(s);
    26     dis[s]=0;
    27     while(!q.empty()) {
    28         int x=q.front();
    29         q.pop();vis[x]=0;
    30         for(int i=head[x];i;i=e[i].next) {
    31             int v=e[i].v;
    32             int u=e[i].u;
    33             int f=e[i].flow;
    34             int s=e[i].spend;
    35             if(dis[u]+s < dis[v]&& f>0) {
    36                 dis[v]=dis[u]+s;
    37                 from[v]=i;
    38                 if(!vis[v]) {
    39                     vis[v]=1;
    40                     q.push(v);
    41                 }
    42             }
    43         }
    44     }
    45     return dis[t]!=inf;
    46     
    47 }
    48 void work() {
    49     int mn=inf;
    50     for(int i=t;i!=s;i=e[from[i]].u)
    51         mn=min(mn,e[from[i]].flow);
    52     for(int i=t;i!=s;i=e[from[i]].u) {
    53         e[from[i]].flow-=mn;
    54         e[from[i]^1].flow+=mn; 
    55         ans+=mn*e[from[i]].spend;
    56     }
    57 }
    58 
    59 int main()
    60 {
    61     scanf("%d",&n);
    62        //1到n代表人
    63        //n+1到n+n代表工作
    64        //0代表超级源点
    65        //n+n+1代表超级汇点
    66     for(int i=1;i<=n;++i)
    67         for(int j=1;j<=n;++j)
    68             scanf("%d",&a[i][j]),add_node(i,j+n,1,a[i][j]),add_node(j+n,i,0,-a[i][j]);
    69     s=0,t=n+n+1;
    70     for(int i=1;i<=n;++i)add_node(s,i,1,0),add_node(i,s,0,0),add_node(n+i,t,1,0),add_node(t,n+i,0,0);
    71 
    72         //建边后直接套板子
    73     while(SPFA()) work();
    74     printf("%d
    ",ans);
    75     
    76     //清空再来一遍, 存一遍的骚操作蒟蒻表示掌握不来╮(╯▽╰)╭
    77     memset(e,0,sizeof(e));
    78     memset(head,0,sizeof(head));
    79     memset(from,0,sizeof(from));
    80     memset(vis,0,sizeof(vis));
    81     memset(dis,0,sizeof(dis));
    82     ans=0;tot=1;
    83     
    84         //基本就是上面在复制一遍
    85     for(int i=1;i<=n;++i)
    86         for(int j=1;j<=n;++j)
    87             add_node(i,j+n,1,-a[i][j]),add_node(j+n,i,0,a[i][j]);
    88     s=0,t=n+n+1;
    89     for(int i=1;i<=n;++i)add_node(s,i,1,0),add_node(i,s,0,0),add_node(n+i,t,1,0),add_node(t,n+i,0,0);
    90     while(SPFA()) work();
    91     printf("%d",-ans);
    92     return 0;
    93 }
  • 相关阅读:
    Unity apk开机自启动一次
    Unity调用Android
    实验 1 Linux 系统的安装和常用命令
    课堂测试3第一阶段数据清洗
    Tutorial_6 运行结果
    Command 'ifconfig' not found, but can be installed with: sudo apt install net-tools VM Ubuntu 解决方案
    《规划极限编程》阅读笔记03
    软件工程_个人课程总结
    《规划极限编程》阅读笔记02
    学习进度_第十六周
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/9269684.html
Copyright © 2011-2022 走看看