最小费用最大流poj2516

来源:互联网 发布:甜甜圈烤机软件 编辑:程序博客网 时间:2024/05/16 05:19
#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <math.h>#include <map>#include <set>#include <vector>#include <queue>#define LL long long#define inf 0x3f3f3f3fusing namespace std;const int N = 1e3+10;struct node{    int to,flow,cost;    int next;}edge[10000];int head[N];//前向星int sK[N][N];//商店需求量int hK[N][N];//仓库存储量int mK[N][N];//仓库到商店的费用int sN[N];//所有商店一共需要第K种物品多少int hN[N];//所有仓库一共存储第K种物品多少int pre[N];//记录前驱,记录的是edge的编号int n,m,k,top;int s,e,ans;void init(){    top = 0,s = 0,e = n+m+1;    memset(head,-1,sizeof(head));}void add(int u,int v,int f,int c){    edge[top]={v,f,c,head[u]};    head[u] = top++;}int dis[N];bool vis[N];bool EK_spfa(){    queue<int>q;    memset(dis,inf,sizeof(dis));    memset(vis,false,sizeof(vis));    memset(pre,-1,sizeof(pre));    dis[s] = 0;    vis[s] = true;    q.push(s);    while(!q.empty()){        int u = q.front();        q.pop();        vis[u] = false;        for(int i = head[u]; ~i; i = edge[i].next){            if(dis[edge[i].to] > dis[u]+edge[i].cost&&edge[i].flow){                dis[edge[i].to] = dis[u]+edge[i].cost;                pre[edge[i].to] = i;                if(!vis[edge[i].to]){                    vis[edge[i].to] = true;                    q.push(edge[i].to);                }            }        }    }    return pre[e]!=-1;}bool EK_Max_Flow(int t){    int cost_ans,flow_ans,mn;    cost_ans = flow_ans = 0;    while(EK_spfa()){        mn = inf;        for(int i = pre[e]; ~i; i = pre[edge[i^1].to]){            mn = min(mn,edge[i].flow);        }        for(int i = pre[e]; ~i; i = pre[edge[i^1].to]){            edge[i].flow -= mn;            edge[i^1].flow += mn;            cost_ans += edge[i].cost*mn;        }        flow_ans += mn;    }    if(flow_ans != sN[t])return true;    ans += cost_ans;    return false;}int main(){    while(~scanf("%d%d%d",&n,&m,&k),n||m||k){        //商店        memset(sN,0,sizeof(sN));        memset(hN,0,sizeof(hN));        for(int i = 1; i <= n; ++i){            for(int j = 1; j <= k; ++j){                scanf("%d",&sK[i][j]);                sN[j] += sK[i][j];            }        }        //仓库        for(int i = 1; i <= m; ++i){            for(int j = 1; j <= k; ++j){                scanf("%d",&hK[i][j]);                hN[j] += hK[i][j];            }        }        bool flag = false;        for(int i = 1; i <= k; ++i){            if(sN[i]>hN[i])flag=true;        }        ans = 0;        for(int i = 1; i <= k; ++i){            for(int j = 1; j <= n; ++j){                for(int l = 1; l <= m; ++l){                    scanf("%d",&mK[j][l]);                }            }            if(flag)continue;            init();            for(int j = 1; j <= m; ++j){                add(s,j,hK[j][i],0);                add(j,s,0,0);            }            for(int j = 1; j <= n; ++j){                add(j+m,e,sK[j][i],0);                add(e,j+m,0,0);            }            for(int j = 1; j <= m; ++j){                for(int l = 1; l <= n; ++l){                    add(j,l+m,inf,mK[l][j]);                    add(l+m,j,0,-mK[l][j]);                }            }            flag = EK_Max_Flow(i);        }        if(flag){            printf("-1\n");        }        else{            printf("%d\n",ans);        }    }    return 0;}

0 0