您的位置:首页 > 其它

[图论] NKOJ 1952 运输问题

2017-07-09 16:05 169 查看
P1952【线性规划与网络流24题 17】运输问题

时间限制 : 10000 MS   空间限制 : 65536 KB

问题描述

W公司有m个仓库和n 个零售商店。第i 个仓库有ai个单位的货物;第j个零售商店需要bj个单位的货物。

货物供需平衡,即sigma(ai)==sigma(bj)。

从第i个仓库运送每单位货物到第j个零售商店的费用为Cij。试设计一个将仓库中所有货物运送到零售商店的运输方案,

使总运输费用最少。

输入格式

第1行有2 个正整数m和n,分别表示仓库数和零售商店数。

接下来的一行中有m个正整数ai,1≤i≤m,表示第i个仓库有ai个单位的货物。

再接下来的一行中有n个正整数bj,1≤j≤n,表示第j个零售商店需要bj个单位的货物。

接下来的m行,每行有n个整数,表示从第i个仓库运送每单位货物到第j个零售商店的费用Cij。

输出格式

程序运行结束时,将计算出的最少运输费用和最多运输费用输出

样例输入

2 3

220 280

170 120 210

77 39 105

150 186 122

样例输出

48500 

69140

提示

1<=n,m<=100

0<=Ai,Bi,Cij<=1000

一道裸题,最小费用最大流和最大费用最大流的结合。

题解:

#include<cstdio>
#include<cstdlib>
#include<queue>
#include<memory.h>
#define MAX 1000
#define inf 1e8
#define reset(x) memset(x,0,sizeof(x))
using namespace std;
int t1[MAX],t2[MAX],b[MAX][MAX],c[MAX][MAX],w[MAX][MAX],path[MAX],max_flow,min_cost;
int dis[MAX],pts;
int flag[MAX];
int T,s=1;
queue<int>q;
void addflow()  //修改路径值
{
int flow,i;
flow=inf;i=T;
while(i!=s)
{
if(flow>c[path[i]][i])flow=c[path[i]][i];
i=path[i];
}
max_flow+=flow;
min_cost+=flow*dis[T];
i=T;
while(i!=s)
{
c[path[i]][i]-=flow;
c[i][path[i]]+=flow;
i=path[i];
}
}
bool find_path(int s) //SPFA
{
int i;
for(i=1;i<=T;i++){dis[i]=inf;path[i]=-1;flag[i]=false;}
dis[s]=path[s]=0;
flag[s]=true;
q.push(s);
while(q.size())
{
int j=q.front();
q.pop();
flag[j]=false;
for(i=1;i<=T;i++)
{
if((c[j][i]>0)&&(dis[i]>dis[j]+w[j][i]))
{
dis[i]=dis[j]+w[j][i];
path[i]=j;
if(!flag[i])
{
flag[i]=true;
q.push(i);
}
}
}
}
if(dis[T]<inf)return true;
else return false;
}
int main()
{
int m,n;
scanf("%d %d",&m,&n);
T=pts=m+n+2;
for(int i=1;i<=m;i++)
{
scanf("%d",&t1[i]);
c[1][i+1]=t1[i];
}
for(int i=1;i<=n;i++)
{
scanf("%d",&t2[i]);
c[1+m+i][T]=t2[i];
/*代价默认为0,不需要重置*/
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&b[i][j]);
w[i+1][m+j+1]=b[i][j];
w[m+j+1][i+1]=-b[i][j];
c[i+1][1+m+j]=inf;
}
}
while(find_path(s)==true)
{
addflow();
}
printf("%d\n",min_cost);
max_flow=0;
min_cost=0;
reset(dis);
reset(path);
reset(w);
reset(c);
for(int i=1;i<=m;i++)
{
c[1][i+1]=t1[i];
}
for(int i=1;i<=n;i++)
{
c[1+m+i][T]=t2[i];
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
w[i+1][m+j+1]=-b[i][j];
w[m+j+1][i+1]=b[i][j];
c[i+1][1+m+j]=inf;
}
}
while(find_path(s)==true)
{
addflow();
}
printf("%d",-min_cost);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图论 费用最大流