欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

POJ 2516 Minimum Cost

程序员文章站 2022-05-08 23:51:31
...

第一道费用流的题目,看了别人博客大概学会了这种算法,就是问如果现在流量也是有单位费用的,如何最大流且有最小费用? 解法是一种贪心,不停地去找费用最小的最短路,最后到无法增广时得到最小费用最大流。这题我用的邻接矩阵,注意题目的图必须分成K个去做,稍微有点复杂,但是基本是模版题,我的建图原则是源点与供应商的最大流量是它能提供的商品,供应商与商店流量无限大,商店与汇点的最大流量是它需要的商品个数(比较复杂,从9点一直做到了11点半 一直在DEBUG的路上狂奔)

code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define MAXN 150
#define INF 9999999
using namespace std;
int N, M, K;
int E[MAXN][MAXN], supply[MAXN][MAXN],shop[MAXN][MAXN],G[MAXN][MAXN],cost[MAXN][MAXN][MAXN];
int vis[MAXN], d[MAXN], pre[MAXN], a[MAXN];
void build(int cnt)
{
 memset(E,0,sizeof(E));
 memset(G,0,sizeof(G));
 int i, j, k;
 for(i=1;i<=M;i++)
 {
  E[0][i]=supply[i][cnt];
 }
 for(i=1;i<=N;i++)
 {
  E[i+M][105]=shop[i][cnt];
 }
 for(i=1;i<=M;i++)
 {
  for(j=1;j<=N;j++)
  {
   E[i][j+M]=INF;
   G[i][j+M]=cost[cnt][j][i];
  // G[j+M][i]=cost[cnt][j][i];
  }
 }
}
bool spfa(int s,int t,int& flow,int& cost)
{
 for(int i=1;i<=105;i++)
 d[i]=INF;
 memset(a,0,sizeof(a));
 memset(vis,0,sizeof(vis));
 memset(pre,0,sizeof(pre));
 d[s]=0;
 vis[s]=1;
 a[s]=INF;
 queue<int> q;
 q.push(s);
 while(!q.empty())
 {
  int x=q.front();
  q.pop();
  vis[x]=0;
 // cout<<"K"<<x<<endl;
  for(int i=1;i<=105;i++)
  {
   if(E[x][i]&&d[i]>d[x]+G[x][i])
   {
    d[i]=d[x]+G[x][i];
    a[i]=min(a[x],E[x][i]);
    pre[i]=x;
    if(!vis[i]){
     q.push(i);
     vis[i]=1;
    }
   }
  }
 }
 if(d[t]==INF)
  return false;
 flow+=a[t];
 cost+=(long long)d[t]*(long long)a[t];
 for(int i=t;i!=s;i=pre[i])
 {
  E[pre[i]][i]-=a[t];
  E[i][pre[i]]+=a[t];
  G[i][pre[i]]=-G[pre[i]][i];
 }
 return true;
}
int main()
{
 int i, j, k;
 while(1)
 {
 cin>>N>>M>>K;
 if(N==0&&M==0&&K==0)
 break;
// memset(E,0,sizeof(E));
// memset(G,0,sizeof(G));
 memset(supply,0,sizeof(supply));
 memset(shop,0,sizeof(shop));
 memset(cost,0,sizeof(cost));
 for(i=1;i<=N;i++)
 {
  for(j=1;j<=K;j++)
  {
   cin>>shop[i][j];
  }
 }
 for(i=1;i<=M;i++)
 {
  for(j=1;j<=K;j++)
  {
   cin>>supply[i][j];
  }
 }
 for(i=1;i<=K;i++)
 {
  for(j=1;j<=N;j++)
  {
   for(k=1;k<=M;k++)
   {
    cin>>cost[i][j][k];
   }
  }
 }
 int cnt=1, ans=0, flag=0;
 int cost=0;
 while(K--)
 {
  build(cnt);
  int flow=0,sum=0;
 // cout<<cnt<<endl;
  while(spfa(0,105,flow,cost));
  for(i=1;i<=N;i++)
  {
   sum+=shop[i][cnt];
  }
  if(flow!=sum)
   flag=1;
  if(flag)
  break;
  cnt++;
 }
 if(!flag)
 cout<<cost<<endl;
 else
 cout<<-1<<endl;
 }
}

相关标签: POJ