zoukankan      html  css  js  c++  java
  • P4014 分配问题(网络流24题 最大最小费用流)

    题目描述

    有 n 件工作要分配给 n 个人做。第 i个人做第 j 件工作产生的效益为cij 。试设计一个将 n件工作分配给 n 个人做的分配方案,使产生的总效益最大。

    输入格式

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

    接下来的 n 行中,每行有 n 个整数 cij​​,表示第 i 个人做第 j件工作产生的效益为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

    一个人只能修一个工件


      1 #include<bits/stdc++.h>
      2 #define N 505
      3 #define INF LLONG_MAX/2 
      4 using namespace std;
      5 typedef struct
      6 {
      7     int u,v;
      8     long long flow,cost;//flow 是流量 cost是花费
      9 }ss;
     10 ss edg[N*N];
     11 vector<int>edges[N];//记录每个点 所有和他相连的边吗
     12 int now_edges=0;//等同于sumedg
     13 
     14 void addedge(int u,int v,long long flow,long long cost)
     15 {
     16     edges[u].push_back(now_edges);
     17     edg[now_edges++]=(ss){u,v,flow,cost};
     18     edges[v].push_back(now_edges);
     19     edg[now_edges++]=(ss){v,u,0,-cost};
     20 }
     21 
     22 bool spfa(int s,int t,long long &flow,long long &cost)
     23 {
     24 //    printf("%lld %lld
    ",flow,cost);
     25     long long dis[N];
     26     for(int i=0;i<N;i++)dis[i]=INF;
     27     dis[s]=0;
     28     int vis[N]={0};
     29     vis[s]=1;
     30     queue<int>q;
     31     q.push(s);
     32     int pre[N]={0}; // 记录费用流路径的 记录前驱用的  通过前驱找到路径 然后最后会修改这个路径
     33     long long  maxflow[N]={0};
     34     maxflow[s]=INF;
     35     
     36     while(!q.empty())
     37     {
     38         int now=q.front();
     39         q.pop();
     40         vis[now]=0;
     41         
     42         int Size=edges[now].size();
     43         for(int i=0;i<Size;i++)
     44         {
     45             ss &e=edg[edges[now][i]];
     46             
     47             if(e.flow>0&&dis[e.v]>dis[now]+e.cost)
     48             {
     49                 dis[e.v]=dis[now]+e.cost;
     50                 pre[e.v]=edges[now][i];
     51                 maxflow[e.v]=min(maxflow[now],e.flow);
     52                 
     53                 if(!vis[e.v])
     54                 {
     55                     q.push(e.v);
     56                     vis[e.v]=1;
     57                 }
     58             }
     59         }        
     60     }
     61     
     62     if(dis[t]==INF)return false;
     63     
     64     flow+=maxflow[t];
     65     cost+=dis[t]*maxflow[t];
     66     
     67     long long now=t;
     68     while(now!=s)
     69     {
     70         edg[pre[now]].flow-=maxflow[t];
     71         edg[pre[now]^1].flow+=maxflow[t];
     72         now=edg[pre[now]].u;
     73     }
     74     
     75     
     76     return true;
     77 }
     78 
     79 void mcmf(int s,int t,long long &flow,long long &cost)
     80 {
     81     while(spfa(s,t,flow,cost)); //一次只能找到一条路径  但是费用流不止一条路径 把全部跑出来
     82 }
     83 void init()
     84 {
     85     now_edges=0;
     86     for(int i=0;i<N;i++)edges[i].clear();
     87 }
     88 
     89 int c[505][505];
     90 
     91 int main()
     92 {
     93     int n,s,t;
     94     scanf("%d",&n);
     95     s=2*n+1;
     96     t=2*n+2;
     97     for(int i=1;i<=n;i++)
     98     for(int j=1;j<=n;j++)
     99     {
    100         scanf("%d",&c[i][j]);
    101     }
    102     
    103     
    104     for(int i=1;i<=n;i++)
    105     for(int j=1;j<=n;j++)addedge(i,j+n,1,c[i][j]);//最短路跑 正边权跑最小费用
    106     
    107     for(int i=1;i<=n;i++)
    108     {
    109         addedge(s,i,1,0);
    110         addedge(i+n,t,1,0);
    111     }
    112     long long flow=0,cost=0;
    113     mcmf(s,t,flow,cost);
    114     printf("%lld
    ",cost);
    115     
    116     init();
    117     
    118     for(int i=1;i<=n;i++)
    119     for(int j=1;j<=n;j++)addedge(i,j+n,1,-c[i][j]);//负边权跑最大费用
    120     
    121     for(int i=1;i<=n;i++)
    122     {
    123         addedge(s,i,1,0);
    124         addedge(i+n,t,1,0);
    125     }
    126     flow=0;
    127     cost=0;
    128     mcmf(s,t,flow,cost);
    129     printf("%lld
    ",-cost);
    130     return 0;
    131 }
  • 相关阅读:
    Documentum常见问题1—Tomcat应用内存溢出
    Documentum常见问题3—保存搜索Saved Searches提示用户对文件柜无权限
    Request.QueryString[]和Request[]的区别
    将money转换成大写汉字
    Windows API(一) 什么是Windows API
    C#将数据导出到Excel汇总
    开始—运行—命令
    手动绘制DataTable
    触发器Deleted表和Inserted表
    功能强大的Regsvr32命令
  • 原文地址:https://www.cnblogs.com/sylvia1111/p/12244921.html
Copyright © 2011-2022 走看看