题目大意:
给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。
对于30%的数据:N<=10,M<=10
对于70%的数据:N<=1000,M<=1000
对于100%的数据:N<=5000,M<=50000
题解:
在 Edmonds-Karp求解最大流的基础上,
用BFS寻找一条增广路改为用SPFA寻找一条单位费用之和最小的增广路,在在残量网络上求最短路,即可求出最小费用最大流。注意:一条反向边y—>x的费用应设为-x到y的单位费用.
代码:
#include <bits/stdc++.h>
#define INF 2333333
#define M 50005
#define N 5005
using namespace std;
int n,m,cnt=1,maxflow,ans,ls[N],v[N],incf[N],dis[N],pre[N];
struct edge {
int to,num,cost,next;
} e[M*2];
void add(int u, int v, int w, int f) {
cnt++; e[cnt].to=v; e[cnt].num=w; e[cnt].cost=f; e[cnt].next=ls[u]; ls[u]=cnt;
cnt++; e[cnt].to=u; e[cnt].num=0; e[cnt].cost=-f; e[cnt].next=ls[v]; ls[v]=cnt;
}
bool spfa(int s, int t){
for (int i=1; i<=n; i++) dis[i]=INF;
memset(v,0,sizeof(v));
queue <int> Q;
Q.push(s);
v[s]=1; dis[s]=0;
incf[s]=INF;
while (Q.size()){
int u=Q.front();
Q.pop();
for (int i=ls[u]; i; i=e[i].next)
if (e[i].num && dis[e[i].to]>dis[u]+e[i].cost){
dis[e[i].to]=dis[u]+e[i].cost;
incf[e[i].to]=min(incf[u],e[i].num);
pre[e[i].to]=i;
if (!v[e[i].to]){
Q.push(e[i].to);
v[e[i].to]=1;
}
}
v[u]=0;
}
return dis[t]!=INF;
}
void update(int s, int t){
int x=t;
while (x!=s){
int i=pre[x];
e[i].num-=incf[t];
e[i^1].num+=incf[t];
x=e[i^1].to;
}
maxflow+=incf[t];
ans+=dis[t]*incf[t];
}
void edmonds_karp(int s, int t){
while (spfa(s,t)) update(s,t);
}
int main() {
int s, t;
scanf("%d%d%d%d",&n,&m,&s,&t);
int u,v,w,f;
for (int i=1; i<=m; i++)
{
scanf("%d%d%d%d",&u,&v,&w,&f);
add(u,v,w,f);
}
edmonds_karp(s,t);
printf("%d %d\n",maxflow,ans);
return 0;
}