最小费用最大流板子
FZSZ Online Judge #707. 最小费用流
题目描述
这是一道模板题。
给定一个图,每条边有容量和费用,使用每条边的单位流量需要支付特定的费用。给定源点 1 和汇点 n,求图的最大流和最大流需要支付的最小费用。
输入格式
第一行两个整数 n、m,表示有 n 个点 m 条边。
从第二行开始的之后 mm 行,每行四个整数 si、ti、ci、wi 表示一条从 sisi 到 titi 的边,容量为 ci,单位流量需要支付的费用为 wi。
输出格式
一行两个整数,分别表示最大流和最大流需要支付的最小费用。
样例
样例输入
8 23
2 3 2147483647 1
1 3 1 1
2 4 2147483647 2
1 4 1 2
2 8 2 0
3 5 2147483647 3
1 5 1 3
3 6 2147483647 4
1 6 1 4
3 8 2 0
3 2 2147483647 0
4 6 2147483647 5
1 6 1 5
4 7 2147483647 6
1 7 1 6
4 8 2 0
4 2 2147483647 0
5 8 0 0
5 2 2147483647 0
6 8 0 0
6 2 2147483647 0
7 8 0 0
7 2 2147483647 0
样例输出
6 24
数据范围与提示
1≤n≤400,0≤m≤15000,wi≥0,保证输入数据、中间结果以及答案在 32 位有符号整数范围内。
#include<iostream> #include<cstdio> #include<queue> #define M 100000 #define INF 2147483647 #define re register using namespace std; queue<long long>q; long long ans,n,m; long long nxt[M+1],las[M+1],to[M+1],v[M+1],w[M+1],dis[M+1],inq[M+1],walk[M+1]; long long tot=1,t,S,T; inline void add(long long x,long long y,long long _v,long _w){ nxt[++tot]=las[x]; las[x]=tot; to[tot]=y; v[tot]=_v; w[tot]=_w; } inline void adde(long long x,long long y,long long v,long long w){ add(x,y,v,w); add(y,x,0,-w); } long long x,y,_w,_v; inline long long bfs(){ for(re long long i=0;i<=n;i++) inq[i]=walk[i]=0,dis[i]=(long long)INF*INF; q.push(S); dis[S]=0; inq[S]=1; long long now; while(!q.empty()){ now=q.front(); q.pop(); inq[now]=0; for(re long long i=las[now];i;i=nxt[i]) if(v[i]&&dis[to[i]]>dis[now]+w[i]){ dis[to[i]]=dis[now]+w[i]; if(!inq[to[i]]){ inq[to[i]]=1; q.push(to[i]); } } } return dis[T]!=(long long)INF*INF?1:0; } inline long long dfs(long long now,long long f){ if(now==T){ ans+=(long long)dis[now]*f; return f; } long long d,ret=0; walk[now]=1; for(re long long i=las[now];i&&f;i=nxt[i]) if(!walk[to[i]]&&v[i]&&dis[to[i]]==dis[now]+w[i]){ d=dfs(to[i],v[i]<f?v[i]:f); f-=d; ret+=d; v[i]-=d; v[i^1]+=d; } walk[now]=0; if(!ret) dis[now]=-INF; return ret; } inline void dinic(){ long long cnt=0; while(bfs()) cnt+=dfs(S,INF); printf("%lld %lld\n",cnt,ans); } int main(){ scanf("%lld%lld",&n,&m); S=1; T=n; for(re long long i=1;i<=m;i++){ scanf("%lld%lld%lld%lld",&x,&y,&_w,&_v); adde(x,y,_w,_v); } dinic(); return 0; }