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行好长,,,第一次做最小费用最大流,出现错误希望大家指正~~

  • 相关阅读:
    冰蝎,从入门到魔改
    红蓝对抗——加密Webshell“冰蝎”攻防
    DGA域名的今生前世:缘起、检测、与发展
    DNS隐藏隧道的使用
    DPI (Deep Packet Inspection) 深度包检测技术
    中国菜刀原理
    一句话木马和中国菜刀的结合拿webshell
    十大黑客工具之一——中国菜刀
    十大ATT&CK攻击技战术
    防守方新秘籍:MITRE 发布主动防御指导框架Shield
  • 原文地址:https://www.cnblogs.com/Patrickcxt/p/3247101.html
Copyright © 2011-2022 走看看