最小费用最大流
可以发现相比最大流多了一个单位流量费用的限制
那么原来利用bfs找路径的思想就不可行了,因为找的路径代价可能很大
而且
扫描二维码关注公众号,回复:
11414468 查看本文章
#include <bits/stdc++.h>
using namespace std;
const int maxn=50009;
const int inf=1e9;
int n,m,s,t;
int maxflow,mincost;
int dis[maxn],head[maxn<<1],cnt=1,incf[maxn],pre[maxn],vis[maxn];
struct EDGE{
int to,nxt,w,flow;//分别代表
}d[maxn<<1];
void add(int u,int v,int flow,int w)//flow最大流量,w单位费用
{
d[++cnt].to=v,d[cnt].flow=flow,d[cnt].w=w,d[cnt].nxt=head[u],head[u]=cnt;
}
bool spfa()
{
queue<int>q;
for(int i=0;i<=n;i++) dis[i]=inf;
memset(vis,0,sizeof(vis));
q.push(s);
dis[s]=0,vis[s]=1;
incf[s] = inf;//初始流量无限大
while( !q.empty() )
{
int u=q.front(); q.pop();
vis[u]=0;//出队
for(int i=head[u];i;i=d[i].nxt)
{
if( !d[i].flow ) continue;//无流量了
int v=d[i].to;
if( dis[v]>dis[u]+d[i].w )
{
dis[v]=dis[u]+d[i].w;
incf[v] = min(incf[u],d[i].flow);//更新当前流量
pre[v]=i;//记录从哪条边过来的
if( !vis[v] ) vis[v]=1,q.push(v);
}
}
}
if( dis[t]==inf ) return 0;
return 1;
}
void dinic()
{
while( spfa() )
{
int x=t;//倒回去找路径
maxflow+=incf[t];
mincost+=dis[t]*incf[t];
int i;
while(x != s)
{
i=pre[x];
d[i].flow-=incf[t];//减去流量
d[i^1].flow+=incf[t];//加上流量
x = d[i^1].to;//因为是倒回去,所以利用反向边倒回去
}
}
}
int main()
{
cin >> n >> m >> s >> t;
for(int i=1;i<=m;i++)
{
int l,r,w,x;
cin >> l >> r >> w >> x;
add(l,r,w,x); add(r,l,0,-x);
}
dinic();
cout << maxflow << " " << mincost;
}