题目
给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。
分析
spfa然后修改每次的流量。
代码
#include <cstdio>
#include <queue>
using namespace std;
struct node{int y,next,w,c;}e[100005]; bool v[5001];
int dis[5001],answer,ans,x,y,w,c,n,m,s,t,k=1,ls[5001],pre[5001];
void add(int x,int y,int w,int c){
e[++k].y=y; e[k].w=w; e[k].c=c; e[k].next=ls[x]; ls[x]=k;
e[++k].y=x; e[k].w=0; e[k].c=-c;e[k].next=ls[y]; ls[y]=k;
}
bool spfa(){//spfa
queue<int>q;
for (int i=1;i<=n;i++) v[i]=0;
for (int i=1;i<=n;i++) dis[i]=707406378;
dis[s]=0; v[s]=1; q.push(s);
while (q.size()){
int u=q.front(); q.pop();
for (int i=ls[u];i;i=e[i].next)
if (e[i].w>0&&dis[u]+e[i].c<dis[e[i].y]){//有容量且费用更少吗
dis[e[i].y]=dis[u]+e[i].c; pre[e[i].y]=i;//记录前驱
if (!v[e[i].y]) v[e[i].y]=1,q.push(e[i].y);
}
v[u]=0;
}
if (dis[t]<707406378) return 1; else return 0;
}
void update(){
m=2147483647; int x=t;
while (x!=s) m=min(m,e[pre[x]].w),x=e[pre[x]^1].y;//统计
ans+=dis[t]*m; answer+=m; x=t;
while (x!=s) e[pre[x]].w-=m,e[pre[x]^1].w+=m,x=e[pre[x]^1].y;//回去修改
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i=1;i<=m;i++) scanf("%d%d%d%d",&x,&y,&w,&c),add(x,y,w,c);
while (spfa()) update();
return !printf("%d %d",answer,ans);
}