洛谷P3381 - 【模板】最小费用最大流
题意简述
模板题啦~
题解
每次都以费用作为边权求一下最短路,然后沿着最短路增广。
Code
//【模板】最小费用最大流
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
inline char gc()
{
static char now[1<<16],*S,*T;
if(S==T) {T=(S=now)+fread(now,1,1<<16,stdin); if(S==T) return EOF;}
return *S++;
}
inline int read()
{
int x=0,f=1; char ch=gc();
while(ch<'0'||'9'<ch) {if(ch=='-') f=-1; ch=gc();}
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int const N=5e3+10;
int const M=5e4+10;
int const INF=0x3F3F3F3F;
int n,m,s,t;
int cnt,h[N];
struct edge{int v,c,w,nxt;} ed[M<<1];
void edAdd(int u,int v,int c,int w)
{
++cnt; ed[cnt].v=v,ed[cnt].c=c,ed[cnt].w=w; ed[cnt].nxt=h[u],h[u]=cnt;
++cnt; ed[cnt].v=u,ed[cnt].c=0,ed[cnt].w=-w; ed[cnt].nxt=h[v],h[v]=cnt;
}
int dst[N],pre[N]; int q[N],op,cl; bool in[N];
bool SPFA()
{
op=cl=0;
memset(dst,0x3F,sizeof dst);
memset(pre,0,sizeof pre);
dst[s]=0; in[q[++cl%N]=s]=true;
while(op<cl)
{
int u=q[++op%N]; in[u]=false;
for(int i=h[u];i;i=ed[i].nxt)
{
int v=ed[i].v,w=ed[i].w;
if(dst[u]+w<dst[v] && ed[i].c)
{
pre[v]=i; dst[v]=dst[u]+w;
if(!in[v]) in[q[++cl%N]=v]=true;
}
}
}
return dst[t]<INF;
}
int main()
{
n=read(),m=read(); s=read(),t=read();
cnt=1;
for(int i=1;i<=m;i++)
{
int u=read(),v=read(),c=read(),w=read();
edAdd(u,v,c,w);
}
int flow=0,cost=0;
while(SPFA())
{
int fl=INF,u=t;
while(pre[u]) fl=min(fl,ed[pre[u]].c),u=ed[pre[u]^1].v;
flow+=fl; cost+=fl*dst[t];
u=t;
while(pre[u]) ed[pre[u]].c-=fl,ed[pre[u]^1].c+=fl,u=ed[pre[u]^1].v;
}
printf("%d %d\n",flow,cost);
return 0;
}