【题意】:有n个商店,m个供应商,k种商品,给出每个商店对每种商品的需求,每个供应商对于每种商品的库存,和对于每种商品,每个供应商运到每个商店的费用。
问:能否满足每个商店的需求,如果能,输出最少的费用;否则输出-1。
【题解】:这是一场个人赛的题目,当时一开始没反应过来是最小费用流,到我意识到的时候已经没有时间敲代码了。
其实这题就是好裸的最小费用流,只需要注意一点,对于每一种商品各自构一次图,跑最小费用流即可。至今不明白为什么k个图没联系,弄在一起跑费用流会超时。
问:能否满足每个商店的需求,如果能,输出最少的费用;否则输出-1。
【题解】:这是一场个人赛的题目,当时一开始没反应过来是最小费用流,到我意识到的时候已经没有时间敲代码了。
其实这题就是好裸的最小费用流,只需要注意一点,对于每一种商品各自构一次图,跑最小费用流即可。至今不明白为什么k个图没联系,弄在一起跑费用流会超时。
对于每个构图就是 s->供应商->商店->t,最后判断一下最大流是否等于各个商店的需求和即可。
算法一次敲对了,不过已经判断出错误就没继续输入了,坑爹啊
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int n_max=105;
const int m_max=10005;
const int inf=1<<30;
struct edge
{
int u,v,cap,cost,pre;
void add(int pu,int pv,int pcap,int pcost,int ppre)
{
u=pu;
v=pv;
cap=pcap;
cost=pcost;
pre=ppre;
}
}e[m_max];
int ne;
int head[n_max];
int sup[n_max][n_max],need[n_max][n_max];
int min_cost,max_flow;
void init()
{
ne=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int cap,int cost)
{
e[ne].add(u,v,cap,cost,head[u]);
head[u]=ne++;
e[ne].add(v,u,0,-cost,head[v]);
head[v]=ne++;
}
void min_cost_max_flow(int s,int t)
{
min_cost=max_flow=0;
while(true)
{
int p[n_max];
memset(p,-1,sizeof(p));
int d[n_max];
int i;
for(i=0;i<n_max;i++)
{
d[i]=inf;
}
d[s]=0;
bool inq[n_max];
memset(inq,0,sizeof(inq));
inq[s]=true;
queue<int> q;
q.push(s);
int u,v;
while(!q.empty())
{
u=q.front();
q.pop();
inq[u]=false;
for(i=head[u];i!=-1;i=e[i].pre)
{
v=e[i].v;
if(e[i].cap&&d[v]>d[u]+e[i].cost)
{
d[v]=d[u]+e[i].cost;
p[v]=i;
if(!inq[v])
{
q.push(v);
inq[v]=true;
}
}
}
}
if(d[t]==inf)
{
break;
}
int nmin=inf;
for(i=p[t];i!=-1;i=p[e[i].u])
{
nmin=min(nmin,e[i].cap);
}
for(i=p[t];i!=-1;i=p[e[i].u])
{
e[i].cap -= nmin;
e[i^1].cap += nmin;
}
min_cost += d[t]*nmin;
max_flow += nmin;
}
}
int main()
{
int n,m,k,s,t;
while(~scanf("%d%d%d",&n,&m,&k))
{
if(n+m+k==0)
{
break;
}
int i,j,l;
s=0;
t=m+n+1;
for(i=1;i<=n;i++)
{
for(j=1;j<=k;j++)
{
scanf("%d",&need[i][j]);
}
}
for(i=1;i<=m;i++)
{
for(j=1;j<=k;j++)
{
scanf("%d",&sup[i][j]);
}
}
bool bans=true;
int sum_cost=0;
int x;
for(l=1;l<=k;l++)
{
init();
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&x);
addedge(j,m+i,inf,x);
}
}
if(!bans)
{
continue;
}
for(i=1;i<=m;i++)
{
if(sup[i][l])
{
addedge(s,i,sup[i][l],0);
}
}
int needall=0;
for(i=1;i<=n;i++)
{
if(need[i][l])
{
needall+=need[i][l];
addedge(m+i,t,need[i][l],0);
}
}
min_cost_max_flow(s,t);
if(max_flow==needall)
{
sum_cost+=min_cost;
}
else
{
bans=false;
}
}
if(bans)
{
printf("%d\n",sum_cost);
}
else
{
printf("-1\n");
}
}
return 0;
}