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;
}
}