最大流的网络,可看作为辅送一般货物的运输网络,此时,最大流问题仅表明运输网络运输货物的能力,但没有考虑运送货物的费用。在实际问题中,运送同样数量货物的运输方案可能有多个,因此从中找一个输出费用最小的的方案是一个很重要的问题,这就是最小代价流所要讨论的内容。
最小费用最大流问题的模型
给定网络N=(V,E,c,w,s,t),每一弧(vi,vj)属于E上,除了已给容量cij外,还给了一个单位流量的费用w(vi,vj)≥O(简记为wij)。所谓最小费用最大流问题就是要求一个最大流f,使得流的总输送费用取最小值。
W(f)=∑wijfij
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#define Inf 2147483647
using namespace std;
int n,m;
int s,t,x,y,c,w;
int cnt,minn,ans,sum;
int dis[10001],head[250011];
bool vis[10001];
struct edge //邻接表
{
int next,to,c,w;
}e[250011];
struct pre //记录路径
{
int fa,e;
}p[250011];
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
}
void add(int from,int to,int c,int w) //建模
{
e[cnt].to=to;
e[cnt].c=c;
e[cnt].w=w;
e[cnt].next=head[from];
head[from]=cnt++;
}
bool spfa() //最短路不解释
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(p,0,sizeof(p));
queue<int> q;
q.push(s);
vis[s]=1;
dis[s]=0;
while (!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for (int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if (e[i].c && dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
p[v].fa=u;
p[v].e=i;
if (!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
return dis[t]!=0x3f3f3f3f;
}
int main()
{
init();
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&x,&y,&c,&w);
add(x,y,c,w);
add(y,x,0,-w); //反向变的费用为正向边的相反数
}
while (spfa())
{
minn=Inf;
for (int i=t;i!=s;i=p[i].fa)
minn=min(minn,e[p[i].e].c); //求最小流量
for (int i=t;i!=s;i=p[i].fa)
{
e[p[i].e].c-=minn; //正向边
e[p[i].e^1].c+=minn; //反向边
}
ans+=minn; //最大流
sum=sum+minn*dis[t]; //最小花费
}
printf("%d %d\n",ans,sum);
return 0;
}