题目描述
如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。
输入输出格式
输入格式:第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。
输出格式:
一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。
输入输出样例
输入样例#1:
4 5 4 3 4 2 30 2 4 3 20 3 2 3 20 1 2 1 30 9 1 3 40 5
输出样例#1:
50 280
说明
时空限制:1000ms,128M
数据规模:对于100%的数据:N<=5000,M<=50000
样例说明:
如图,最优方案如下:
第一条流为4-->3,流量为20,费用为3*20=60。
第二条流为4-->2-->3,流量为20,费用为(2+1)*20=60。
第三条流为4-->2-->1-->3,流量为10,费用为(2+9+5)*10=160。
故最大流量为50,在此状况下最小费用为60+60+160=280。
故输出50 280。
%:pragma GCC optimize(3)
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int MAXN=5010,MAXM=50010,INF=1e9;
struct XY{int to,pre,cost,cap;}e[2*MAXM];
struct XX{int pre,f,dis;bool b;}v[MAXN];
int n,m,s,t,sz=1,MaxFlow,MinCost,xx,yy,cc,ww;
int las[MAXN],xb[MAXN];
void add(int a,int b,int c,int z){
++sz;e[sz].to=b;e[sz].cap=c;e[sz].cost=z;
e[sz].pre=las[a];las[a]=sz;
}
int BFS(int s,int t){
queue<int> Q;
for (int i=0;i<=n;++i)
v[i].dis=INF,v[i].b=false,v[i].pre=-1;
v[s].b=1;v[s].dis=v[s].pre=0;v[s].f=INF;
Q.push(s);
while (!Q.empty()){
int tmp=Q.front();v[tmp].b=false;Q.pop();
for (int i=las[tmp];i;i=e[i].pre){
int u=e[i].to;
if (e[i].cap>0&&v[u].dis>v[tmp].dis+e[i].cost){
v[u].dis=v[tmp].dis+e[i].cost;
v[u].pre=tmp;xb[u]=i;
v[u].f=min(v[tmp].f,e[i].cap);
if (!v[u].b) v[u].b=1,Q.push(u);
}
}
}
if (v[t].dis>=INF) return 0;return 1;
}
void MinCost_MaxFlow(int s,int t){
while (BFS(s,t)){
int k=t;
while (k!=s){
e[xb[k]].cap-=v[t].f;e[xb[k]^1].cap+=v[t].f;
k=v[k].pre;
}
MaxFlow+=v[t].f;MinCost+=v[t].f*v[t].dis;
}
}
int main(){
scanf("%d %d %d %d",&n,&m,&s,&t);
for (int i=1;i<=m;++i){
scanf("%d%d%d%d",&xx,&yy,&cc,&ww);
add(xx,yy,cc,ww);add(yy,xx,0,-ww);
}
MinCost_MaxFlow(s,t);
printf("%d %d",MaxFlow,MinCost);
return 0;
}