zoukankan      html  css  js  c++  java
  • Poj2516 最小费用最大流

    题目讲的是要从M个货源地提供K中商品个N个店主,不同的店主对不同商品的需求量不同,不同货源地K中商品的存货量也不同,第k种商品从货源地v到店主u的单位商品运输费用也不同,要求出满足所有店主要求的最小运输费用,若无法满足则输出“-1”。

      我的想法是对于每一种商品分开处理, 每一种商品的运输费用都达到最小即可得到总费用最小,一个大循环for(i= 0; i < k; i++); 要求运输第i种商品满足所有店主的费用最小,其实就是求最小费用最大流的问题,将所有k种产品的最小费用加起来也就是总的最小费用了。题目的关键在于对第i种商品如何建图,该题目建成一个二分图,N个店主和M个货源地分为两个部分,可以增加一个超级源点s和一个超级汇点t,s有M条指向货源地的有向边,容量为货源地的存货量,费用为0,N和M个点之间的费用根据输入的val,容量为无穷大,然后N个店主各自有一条边指向汇点t,容量为该店主的需求量,费用为0,建图完成,接下来只需 求K次最小费用最大流就可,如果某一次求出的最大流不等于该中商品的需求量之和,则不满足条件,输出“-1”。

    我的代码实现如下:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <queue>
     4 using namespace std;
     5 const int MAXN = 110;
     6 const int INF = 0x7FFFFFFF;
     7 int cap[MAXN][MAXN], cost[MAXN][MAXN];
     8 int path[MAXN], d[MAXN];
     9 int need[55][55], supply[55][55];
    10 bool inq[MAXN];
    11 int N, c, f;
    12 queue<int> Q;
    13 //求最小费用最大流  
    14 void Min_Cost(int s, int t) {
    15   int i, u, v;
    16   c = 0; f = 0;
    17   while (1) {
    18       memset(inq, 0, sizeof(inq));
    19       for (i = 0; i <= t; i++) d[i] = (i == s? 0 : INF);
    20       Q.push(s);  inq[s] = true;
    21       while (!Q.empty()) {
    22         u = Q.front();  Q.pop();
    23         inq[u] = false;
    24         for (v = 0; v <= t; v++) {
    25             if (cap[u][v] && d[v] > d[u] + cost[u][v]) {
    26                 d[v] = d[u] + cost[u][v];
    27                 path[v] = u;
    28                 if (!inq[v]) {
    29                     inq[v] = true;
    30                     Q.push(v);
    31                 }
    32             }
    33         }
    34       }
    35       if (d[t] == INF) break;
    36       int a = INF;
    37       for (u = t; u != s; u = path[u]) a = (a < cap[path[u]][u]? a : cap[path[u]][u]); 
    38     for (u = t; u !=s; u = path[u]) {
    39       cap[path[u]][u] -= a;
    40       cap[u][path[u]] += a;
    41     }
    42     c += a * d[t];
    43     f += a;
    44   }
    45 }
    46 
    47 int main() {
    48   int i, j, u, v, n, m, k;
    49   while (scanf("%d%d%d", &n, &m, &k), n != 0 || m != 0 || k != 0) {
    50       N = n + m + 1;
    51       int mincost = 0, val;
    52       int s = 0, t = N, flag = 1;
    53       for (i = 1; i <= n; i++)
    54         for (j = 0; j < k; j++)
    55           scanf("%d", &need[i][j]);
    56       for (i = 1; i <= m; i++)
    57         for (j = 0; j < k; j++)
    58           scanf("%d", &supply[i][j]);
    59     for (i = 0; i < k; i++) {
    60       memset(cap, 0, sizeof(cap));
    61       memset(cost, 0, sizeof(cost));
    62       //建图过程 
    63       for (u = 1; u <= n; u++) {
    64           for (v = 1; v <= m; v++) {
    65           scanf("%d", &val);
    66           cost[v][u+m] = val;
    67           cost[u+m][v] = -val;
    68           cap[v][u+m] = INF;
    69         }
    70       }
    71       for (j = 1; j <= m; j++) {
    72           cap[s][j] = supply[j][i];
    73       }
    74       for (j = 1; j <= n; j++) {
    75           cap[j+m][t] = need[j][i];
    76       }
    77       
    78       if (flag) {
    79         Min_Cost(s, t);  
    80         int count = 0;
    81         for (j = 1; j <= n; j++)  //求该中商品的总需求量 
    82           count += need[j][i];
    83         if (f != count) {  //若不相等,则不满足 
    84           flag = 0; 
    85         }
    86         mincost += c;
    87       }
    88     }
    89     if (flag)
    90       printf("%d\n", mincost);
    91     else
    92       printf("-1\n"); 
    93   }
    94   return 0;
    95 }

    我的代码95行好长,,,第一次做最小费用最大流,出现错误希望大家指正~~

  • 相关阅读:
    ffmpeg rtmp推流 视频转码
    java日志发展史 log4j slf4j log4j2 jul jcl 日志和各种桥接包的关系
    nginx stream 流转发,可以转发rtmp、mysql访问流,转发rtmp、jdbc请求
    java web http 转https 通过nginx代理访问
    linux 服务器磁盘挂载
    novnc 通过websockify代理 配置多点访问
    linux 文件服务 minio 安装部署配置
    AOP实现原理,手写aop
    java 泛型
    JAVA反射getGenericSuperclass()用法
  • 原文地址:https://www.cnblogs.com/Patrickcxt/p/3247101.html
Copyright © 2011-2022 走看看