poj 2516 分类: poj templa...


最小费用最大流。模板题,
听说驼峰体能提升逼格。。。


顺便说一句,数据范围有坑。


#include<map>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>

const int MAXM = 505, MAXN = 505, MAXK = 50, INF = 2e8;
const int NodeNum = MAXM+MAXN ,SIZE = MAXM*MAXN+MAXN+MAXM;
const int Ni[2] = {-1,1};

int n, m, k;

int sx[MAXK][MAXM] = {0};
int tx[MAXK][MAXN] = {0};
int mat[MAXM][MAXN] = {0};

struct Edge
{
   int v,cap,co,next;   
}edge[SIZE<<1];
int el, ind, head[NodeNum] = {0};
int s, t;

void NewEdge(int u,int v,int cap,int co)
{
    ++el;edge[el].v = v;
    edge[el].cap = cap;
    edge[el].co = co;
    edge[el].next = head[u];
    head[u] = el;
}
void NewNetEdge(int u,int v,int cap,int cost)
{
    NewEdge(u,v,cap,cost);NewEdge(v,u,0,-cost);
}
int NewNode(){head[++ind] = 0;return ind;}

int mpot[MAXM], npot[MAXN] = {0};
std::pair<int,int>from[NodeNum];
#define Mp(x,y) std::make_pair(x,y)
#define Nn first
#define En second 
int dist[NodeNum];bool flag[NodeNum];
int line[NodeNum],f,r;
void SPFA()
{
//  memset(flag,false,sizeof(flag));    
    for(int i = 1; i <= ind; i++)dist[i] = INF;
    f = r = dist[s] = 0; 
    line[r] = s, r = (r+1)%NodeNum, flag[s] = true;
    while(f!=r)
    {
         int a = line[f]; f = (f+1)%NodeNum; flag[a] = false;

         for(int i = head[a]; i ; i = edge[i].next)
          if(edge[i].cap)
          {
            int p = edge[i].v , tmp = dist[a] + edge[i].co;

            if(tmp < dist[p])
            {
                dist[p] = tmp,from[p] = Mp(a,i);
                if(!flag[p])
                {
                    if(dist[p] <= dist[line[f]])
                        f = (f-1+NodeNum)%NodeNum ,line[f] = p;
                    else
                        line[r] = p, r = (r+1)%NodeNum;
                    flag[p] = true; 
                }
            }
          }
    }
}
int find(int now,int flow)
{
    if(now == s)return flow;

    int y = from[now].En;
    flow = std::min(flow,edge[y].cap);
    flow = find(from[now].Nn,flow);
    edge[y].cap -= flow;
    edge[y+Ni[y&1]].cap += flow;
    return flow;
}
void NetFlow(int &totflow,int &totcost)
{
    totflow = totcost = 0;
    while(1)
    {
        SPFA(); if(dist[t] == INF)break;
        int fflow = find(t,INF);
        totflow += fflow;
        totcost += fflow*dist[t];
    }
}
void BuildGraph(int ss[],int tt[])
{
    el = ind = 0;
    s = NewNode(); t = NewNode();
    for(int i = 1; i <= m ; i++)
    {
      mpot[i] = NewNode();  
      NewNetEdge(s,mpot[i],ss[i],0);
    }
    for(int i = 1; i <= n; i++)
    {
      npot[i] = NewNode();
      NewNetEdge(npot[i],t,tt[i],0);    
    }
    for(int i = 1; i <= m ;i++)
      for(int j = 1; j <= n; j++)
        NewNetEdge(mpot[i],npot[j],INF,mat[i][j]);  
}
int main()
{   
#ifndef ONLINE_JUDGE
    freopen("poj2516.in","r",stdin);
    freopen("poj2516.out","w",stdout);
#endif

    while(1)
    {
        scanf("%d%d%d",&n,&m,&k);
        if(!n && !m && !k) break;

        for(int i = 1; i <= n ; i++)
         for(int j = 1; j <= k; j++)
           scanf("%d",&tx[j][i]);
        for(int i = 1; i <= m ; i++)
         for(int j = 1; j <= k; j++)
           scanf("%d",&sx[j][i]);
        int sigma = 0;   
        for(int i = 1; i <= k; i++)
        {
            for(int p = 1; p <= n; p++)
              for(int q = 1; q <= m; q++)
                 scanf("%d",&mat[q][p]);
            if(sigma == -1)continue;

            BuildGraph(sx[i],tx[i]);

            int flow,cost,sum = 0;
            for(int p = 1; p <= n; p++)sum += tx[i][p];

            NetFlow(flow,cost);
            if(flow == sum)sigma += cost;
            else   sigma = -1;           
        }
        printf("%d\n",sigma);
    }

#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/dashgua/p/4723052.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值