POJ2516费用流
阅读原文时间:2023年07月08日阅读:4

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

目录

目录

题意:传送门

####AC代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <string>
#include <bitset>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
#include <iomanip>
using namespace std;
typedef long long LL;

const int MAXN = 605;
const int MAXE = 4e5 + 7;
const int INF = 0x3f3f3f3f;
struct MCMF {
    int S, T;//源点,汇点
    int tot, n;
    int st, en, maxflow, mincost;
    bool vis[MAXN];
    int head[MAXN], cur[MAXN], dis[MAXN];
    int roade[MAXN], roadv[MAXN], rsz; //用于打印路径
    queue <int> Q;
    struct Edge {
        int v, cap, cost, nxt, flow;
        Edge() {}
        Edge(int a, int b, int c, int d) {
            v = a, cap = b, cost = c, nxt = d, flow = 0;
        }
    } E[MAXE], SE[MAXE];
    void init(int _n) {
        n = _n, tot = 0;
        for(int i = 0; i <= n; i++) head[i] = -1;
    }
    void add_edge(int u, int v, int cap, int cost) {
        E[tot] = Edge(v, cap, cost, head[u]);
        head[u] = tot++;
        E[tot] = Edge(u, 0, -cost, head[v]);
        head[v] = tot++;
    }
    bool adjust() {
        int v, min = INF;
        for(int i = 0; i <= n; i++) {
            if(!vis[i]) continue;
            for(int j = head[i]; ~j; j = E[j].nxt) {
                v = E[j].v;
                if(E[j].cap - E[j].flow) {
                    if(!vis[v] && dis[v] - dis[i] + E[j].cost < min) {
                        min = dis[v] - dis[i] + E[j].cost;
                    }
                }
            }
        }
        if(min == INF) return false;
        for(int i = 0; i <= n; i++) {
            if(vis[i]) {
                cur[i] = head[i];
                vis[i] = false;
                dis[i] += min;
            }
        }
        return true;
    }
    int augment(int i, int flow) {
        if(i == en) {
            mincost += dis[st] * flow;
            maxflow += flow;
            return flow;
        }
        vis[i] = true;
        for(int j = cur[i]; j != -1; j = E[j].nxt) {
            int v = E[j].v;
            if(E[j].cap == E[j].flow) continue;
            if(vis[v] || dis[v] + E[j].cost != dis[i]) continue;
            int delta = augment(v, std::min(flow, E[j].cap - E[j].flow));
            if(delta) {
                E[j].flow += delta;
                E[j ^ 1].flow -= delta;
                cur[i] = j;
                return delta;
            }
        }
        return 0;
    }
    void spfa() {
        int u, v;
        for(int i = 0; i <= n; i++) {
            vis[i] = false;
            dis[i] = INF;
        }
        Q.push(st);
        dis[st] = 0;
        vis[st] = true;
        while(!Q.empty()) {
            u = Q.front(), Q.pop();
            vis[u] = false;
            for(int i = head[u]; ~i; i = E[i].nxt) {
                v = E[i].v;
                if(E[i].cap == E[i].flow || dis[v] <= dis[u] + E[i].cost) continue;
                dis[v] = dis[u] + E[i].cost;
                if(!vis[v]) {
                    vis[v] = true;
                    Q.push(v);
                }
            }
        }
        for(int i = 0; i <= n; i++) {
            dis[i] = dis[en] - dis[i];
        }
    }
    int zkw_flow(int s, int t,int Sum) {
        st = s, en = t;
        spfa();
        mincost = maxflow = 0;
        for(int i = 0; i <= n; i++) {
            vis[i] = false;
            cur[i] = head[i];
        }
        do {
            while(augment(st, INF)) {
                memset(vis, false, n * sizeof(bool));
            }
        } while(adjust());
        if(maxflow!=Sum)return -1;
        return mincost;
    }
}zkw;
//u v 流量 费用
const int N = 55;
inline int ab(int x){return x<0?-x:x;}
int vs,vt;
int n,m,p;
int ar[N][N],br[N][N],cr[N][N];
int main() {
#ifndef ONLINE_JUDGE
    freopen("E://ADpan//in.in", "r", stdin);
    //freopen("E://ADpan//out.out", "w", stdout);
#endif
  while(~scanf("%d%d%d",&n,&m,&p)&&(n+m+p)){
    vs=n+m+1;vt=n+m+2;
    //建p次图
    //1-n客户,n-n+m仓库
    for(int i=1;i<=n;++i){
      for(int j=0,x;j<p;++j){
        scanf("%d",&ar[i][j]);//客户
      }
    }
    for(int i=1;i<=m;++i){
      for(int j=0,x;j<p;++j){
        scanf("%d",&br[i][j]);//仓库
      }
    }
    int ans=0,flag=1;
    for(int h=0;h<p;++h){
      zkw.init(n+m+2);
      int sum=0;
      for(int i=1;i<=n;++i){
        zkw.add_edge(i,vt,ar[i][h],0);
        sum+=ar[i][h];
      }
      for(int i=1;i<=m;++i){
        zkw.add_edge(vs,i+n,br[i][h],0);
      }
      for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j){
          int x;scanf("%d",&x);
          zkw.add_edge(j+n,i,INF,x);
        }
      }
      int tmp = zkw.zkw_flow(vs,vt,sum);
      if(tmp==-1)flag=0;
      ans+=tmp;
    }
    if(flag==0)printf("-1\n");
    else printf("%d\n", ans);
  }
  return 0;
}

####原题目描述: