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;
}