zoukankan      html  css  js  c++  java
  • POJ 2516 【最小费用最大流】.cpp

    题意:

    给出供应商供应的商品量和商家需要的商品量以及某个商品在供应商和商家之间的消耗量

    问商家是否能得到想要的商品量

    如果可以那怎么安排才是最少花费

    输入:

      给出 n m k 表示有n个商家 m个供应商 k个商品

      接下来n行有k个数值表示 第 ni 个商家需要的第k个商品的商品量为ki

      接下来m行有k个数值表示 第 mi 个商家需要的第k个商品的商品量为ki

      接下来的k个n*m矩阵表示第 ki 个商品 又第 mi 个供应商给第 ni 个商家的消耗

      

    思路:

     很明显的最小费用最大流..

      但是建图很特别..

      先求出每个商品的最小花费 然后加起来

      固定了超级源点和每个供应商之间的边(容量为供应商第k个商品的库存, 花费为0) 以及 每个商家和超级汇点之间的边(容量为商家所需要的第k个商品的量, 花费为0)

      然后每次得到第k个商品在商家和供应商之间的消耗

      建图

      求出第k个商品在商家和供应商之间的最小费用最大流..

      求和..

    Tips:

      建图的时候..

      对反向边要增加负消耗量的边..

    Code:

    View Code
      1 #include <stdio.h>
      2 #include <cstring>
      3 #include <algorithm>
      4 using namespace std;
      5 #define clr(x) memset(x, 0, sizeof(x))
      6 const int INF = 0x1f1f1f1f;
      7 
      8 const int MAXN = 210;
      9 int cap[MAXN][MAXN], flow[MAXN][MAXN];
     10 int cost[MAXN][MAXN];
     11 int n, f, c;
     12 
     13 bool vis[MAXN];
     14 int que[MAXN], pre[MAXN], dis[MAXN];
     15 
     16 bool spfa(int s, int e)
     17 {
     18     int front = 0, rear = 0;
     19     for(int u = 0; u <= n; ++u) {
     20         if(u == s) {
     21             que[rear++] = u;
     22             dis[u] = 0;
     23             vis[u] = true;
     24         } else {
     25             dis[u] = INF;
     26             vis[u] = false;
     27         }
     28     }
     29     while(front != rear) {
     30         int u = que[front++];
     31         vis[u] = false;
     32         if(front >= MAXN) front = 0;
     33         for(int v = 0; v <= n; ++v) {
     34             if(cap[u][v] > flow[u][v] && dis[v] > dis[u]+cost[u][v]) {
     35                 dis[v] = dis[u]+cost[u][v];
     36                 pre[v] = u;
     37                 if(!vis[v]) {
     38                     vis[v] = true;
     39                     que[rear++] = v;
     40                     if(rear >= MAXN) rear = 0;
     41                 }
     42             }
     43         }
     44     }
     45     if(dis[e] >= INF) return false;
     46     else return true;
     47 }
     48 
     49 void min_c_f(int s, int e)
     50 {
     51     clr(flow);
     52     c = f = 0;
     53     while(spfa(s, e)) {
     54         int _min = INF;
     55         for(int u = e; u != s; u=pre[u])
     56             _min = min(_min, cap[pre[u]][u]-flow[pre[u]][u]);
     57         for(int u = e; u != s; u = pre[u]) {
     58             flow[pre[u]][u] += _min;
     59             flow[u][pre[u]] -= _min;
     60         }
     61         f += dis[e]*_min;
     62         c += _min;
     63     }
     64 }
     65 
     66 int order[MAXN][MAXN], sup[MAXN][MAXN];
     67 int sum[MAXN];
     68 
     69 int main()
     70 {
     71     int nn, mm, kk;
     72     int i, j, k;
     73     int ans, t;
     74     bool flag;
     75     while(scanf("%d %d %d", &nn, &mm, &kk) != EOF)
     76     {
     77         if(nn == 0 && mm == 0 && kk == 0) break;
     78         ans = 0, n = nn+mm+1;
     79         clr(sum), clr(cap), clr(flow), clr(cost);
     80         flag = true;
     81 
     82         for(i = 0; i < nn; ++i)
     83         for(j = 0; j < kk; ++j) {
     84             scanf("%d", &order[i][j]);
     85             sum[j] += order[i][j];
     86         }
     87 
     88         for(i = 0; i < mm; ++i)
     89         for(j = 0; j < kk; ++j)
     90             scanf("%d", &sup[i][j]);
     91 
     92         for(i = 1; i <= mm; ++i)
     93             for(j = mm+1; j <= nn+mm; ++j)
     94                 cap[i][j] = INF;
     95 
     96         for(int i = 0; i < kk; ++i) {
     97             for(int j = mm+1; j <= mm+nn; ++j)
     98             for(int k = 1; k <= mm; ++k) {
     99                 scanf("%d", &cost[k][j]);
    100                 cost[j][k] = -cost[k][j];       ///!!!!
    101             }
    102             if(!flag) continue;
    103 
    104             for(int j = 1; j <= mm; ++j)
    105                 cap[0][j] = sup[j-1][i];
    106             for(int j = 1; j <= nn; ++j)
    107                 cap[j+mm][n] = order[j-1][i];
    108 
    109             min_c_f(0, n);
    110             if(c < sum[i]) flag = false;
    111             else ans += f;
    112         }
    113 
    114         if(!flag) puts("-1");
    115         else printf("%d\n", ans);
    116     }
    117     return 0;
    118 }

     

    题目链接:http://poj.org/problem?id=2516

  • 相关阅读:
    网页加载进度条
    【转载】通俗易懂,什么是.NET?什么是.NET Framework?什么是.NET Core?
    前端知识复习:Html DIV 图文混排(文字放在图片下边)
    NOPI导出Excel
    C# 发送邮件
    DataSetToList 和 DataTableTolist 转换
    一个修改版的PHP ajax Tree树形菜单
    你的站为什么百度无动于衷——10年老站长的SEO肺腑之言 .
    关于php使用phpqrcode生成二维码的完整源码下载
    php结合phpqrcode生成带图片LOGO的二维码
  • 原文地址:https://www.cnblogs.com/Griselda/p/2709635.html
Copyright © 2011-2022 走看看