含义
每一条边还有一个费用,表示单位流量通过所需费用,要求在保持最大流时,使总费用最少.
方法
在求最大流时,对增广进行修改,原来求边的数量最少,但因无论如何增广都可以求出最大流,因而每次增广可以用找最短路的方法求出总费用最少的路径,且反向边的费用为原来费用的相反数,因为反向边的权值为负,因而不能用迪杰斯提拉,但可以SPFA等来做.
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
#define N 5010
#define M 50010
using namespace std;
int m,n,s,t,bb,first[N],need[N],last[N],ans,jl[N];
bool in[N];
struct Bn
{
int next,to,ll,cst;
}bn[M*2];
queue<int>que;
inline void add(int u,int v,int p,int q)
{
bn[bb].cst=q;
bn[bb].ll=p;
bn[bb].to=v;
bn[bb].next=first[u];
first[u]=bb;
bb++;
}
inline bool bfs()
{
int i,j,p,q,mn=INF;
memset(need,INF,sizeof(need));
memset(last,0,sizeof(last));
memset(in,0,sizeof(in));
for(;!que.empty();que.pop());
que.push(s);
need[s]=0;
for(;!que.empty();)
{
q=que.front();
que.pop();
in[q]=0;
for(p=first[q];p!=-1;p=bn[p].next)
{
if(!bn[p].ll) continue;
if(need[q]+bn[p].cst<need[bn[p].to])
{
need[bn[p].to]=need[q]+bn[p].cst;
last[bn[p].to]=q;
jl[bn[p].to]=p;
if(!in[bn[p].to]&&bn[p].to!=t)
{
in[bn[p].to]=1;
que.push(bn[p].to);
}
}
}
}
if(need[t]==INF) return 0;
for(p=t;p!=s;p=last[p])
{
mn=min(bn[jl[p]].ll,mn);
}
ans+=mn;
for(p=t;p!=s;p=last[p])
{
bn[jl[p]].ll-=mn;
bn[jl[p]^1].ll+=mn;
}
return 1;
}
int main()
{
// freopen("1.txt","r",stdin);
memset(first,-1,sizeof(first));
int i,j,a,b,c,d;
cin>>n>>m>>s>>t;
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
add(a,b,c,d);
add(b,a,0,-d);
}
for(;bfs(););
cout<<ans<<" ";
ans=0;
for(i=1;i<m*2;i+=2)
{
ans-=bn[i].ll*bn[i].cst;
}
cout<<ans;
}