zoukankan      html  css  js  c++  java
  • POJ2516

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

    解题思路:

      最小费用最大流,这个没什么疑问。但此题小难点在于读题,大难点在于建图。

      首先,供应量小于需求量的时候直接输出“-1”。

      供大于或等于求的情况,一开始我将每个供应商和每个购买人都拆成K个点,将所有供应商的点和超级源点相连,流量限制为库存量,费用为0;将所有购买人的点和超级汇点相连,流量限制为购买量,费用为0;而购买方和供应方之间的连线的流量限制则为inf,费用如题目中给出的。但是这种建图方式一直T......一度绝望到以为我的模板有问题,修修补补了半天,还是T......上网查了题解,发现大家的建图方式跟我不一样:大家都是把根据K种商品,建K个图逐一求最小费用最大流,答案就是K个图的最小费用之和。稍微改了一下,AC.......醉........至于为什么........我也不太懂,容我明天去问问师兄。

    AC代码:

      1 #include <cstdio>
      2 #include <vector>
      3 #include <queue>
      4 #include <cstring>
      5 using namespace std;
      6 
      7 const int MAXN = 5000;
      8 const int MAXM = 100000;
      9 const int INF = 0x3f3f3f3f;
     10 struct rec {
     11     int from, to, cost, cap;
     12 }r[55][2550];
     13 struct Edge {
     14     int to, next, cap, flow, cost;
     15 }edge[MAXM];
     16 int head[MAXN], tol;
     17 int pre[MAXN], dis[MAXN];
     18 bool vis[MAXN];
     19 int N;
     20 void init(int n) {
     21     N = n;
     22     tol = 0;
     23     memset(head, -1, sizeof(head));
     24 }
     25 void addedge(int u, int v, int cap, int cost) {
     26     edge[tol].to = v;
     27     edge[tol].cap = cap;
     28     edge[tol].cost = cost;
     29     edge[tol].flow = 0;
     30     edge[tol].next = head[u];
     31     head[u] = tol++;
     32     edge[tol].to = u;
     33     edge[tol].cap = 0;
     34     edge[tol].cost = -cost;
     35     edge[tol].flow = 0;
     36     edge[tol].next = head[v];
     37     head[v] = tol++;
     38 }
     39 bool spfa(int s, int t) {
     40     queue<int>q;
     41     for (int i = 0; i < N; i++) {
     42         dis[i] = INF;
     43         vis[i] = false;
     44         pre[i] = -1;
     45     }
     46     dis[s] = 0;
     47     vis[s] = true;
     48     q.push(s);
     49     while (!q.empty()) {
     50         int u = q.front();
     51         q.pop();
     52         vis[u] = false;
     53         for (int i = head[u]; i != -1; i = edge[i].next) {
     54             int v = edge[i].to;
     55             if (edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost){
     56                 dis[v] = dis[u] + edge[i].cost;
     57                 pre[v] = i;
     58                 if (!vis[v]){
     59                     vis[v] = true;
     60                     q.push(v);
     61                 }
     62             }
     63         }
     64     }
     65     if (pre[t] == -1)    return false;
     66     else    return true;
     67 }
     68 int minCostMaxflow(int s, int t, int &cost){
     69     int flow = 0;
     70     cost = 0;
     71     while (spfa(s, t)) {
     72         int Min = INF;
     73         for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) {
     74             if (Min > edge[i].cap - edge[i].flow)
     75                 Min = edge[i].cap - edge[i].flow;
     76         }
     77         for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) {
     78             edge[i].flow += Min;
     79             edge[i ^ 1].flow -= Min;
     80             cost += edge[i].cost * Min;
     81         }
     82         flow += Min;
     83     }
     84     return flow;
     85 }
     86 int sup[55][55], buy[55][55];
     87 int main() {
     88     int N, M, K;
     89     int need[53], have[53];
     90     while (scanf("%d%d%d", &N, &M, &K) == 3 && (N || M || K)) {
     91         memset(need, 0, sizeof(need));
     92         memset(have, 0, sizeof(have));
     93         int c;
     94         for (int i = 1; i <= N; i++) {
     95             for (int j = 1; j <= K; j++) {
     96                 scanf("%d", &c);
     97                 need[j] += c;
     98                 buy[j][i] = c;
     99             }
    100         }
    101         for (int i = 1; i <= M; i++) {
    102             for (int j = 1; j <= K; j++) {
    103                 scanf("%d", &c);
    104                 have[j] += c;
    105                 sup[j][i] = c;
    106             }
    107         }
    108         bool yes = true;
    109         for (int j = 1; j <= K; j++) {
    110             if (have[j]<need[j]) yes = false;
    111         }
    112 
    113         int ans = 0;
    114         for (int k = 1; k <= K; k++) {
    115             if (yes)
    116                 init(N + M + 2);
    117             for (int i = 1; i <= N; i++) {
    118                 for (int j = 1; j <= M; j++) {
    119                     scanf("%d", &c);
    120                     if (yes)
    121                         addedge(j, M + i, INF, c);
    122                 }
    123             }
    124             if (yes) {
    125                 for (int i = 1; i <= M; i++)
    126                     addedge(0, i, sup[k][i], 0);
    127                 for (int i = 1; i <= N; i++)
    128                     addedge(M + i, N + M + 1, buy[k][i], 0);
    129                 int cost;
    130                 minCostMaxflow(0, N + M + 1, cost);
    131                 ans += cost;
    132             }
    133         }
    134         if (!yes)
    135             printf("-1
    ");
    136         else
    137             printf("%d
    ", ans);
    138     }
    139     return 0;
    140 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    XidianOJ 1096 数的拆分
    XidianOJ 1183 Water Problem: Items divided
    XidianOJ 1182 Chinese Paladin – Qi’s troubles
    XidianOJ 1112 Too stupid
    XidianOJ 1120 Gold of Orz Pandas
    XidianOJ 1177 Counting Stars
    XidianOJ 1076 小W喜欢的数字
    XidianOJ 1095 派对
    XidianOJ 1055 如此遍历
    XidianOJ 1145 数学题
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/7450770.html
Copyright © 2011-2022 走看看