(前置:20191025 练习:网络流(最大流最小割) ,20191018 专题:网络流(最大流最小割))
全名最小费用最大流
就是在网络流的基础上给每边加上了单位流量的费用,求流量最大时的最小费用
代码也很简单
把网络流中的BFS找深度改成spfa找费用就行
关于spfa:他死了
注意细节(代码里有标注)
P3381【模板】最小费用最大流
题目描述
如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。
输入格式
第一行包含四个正整数 N 、 M 、 S 、 T N、M、S、T N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来M行每行包含四个正整数 u i 、 v i 、 w i 、 f i u_i、v_i、w_i、f_i ui、vi、wi、fi,表示第i条有向边从 u i u_i ui出发,到达 v i v_i vi,边权为 w i w_i wi(即该边最大流量为 w i w_i wi),单位流量的费用为 f i f_i fi。
输出格式
一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。
输入输出样例
输入
4 5 4 3
4 2 30 2
4 3 20 3
2 3 20 1
2 1 30 9
1 3 40 5
输出
50 280
说明/提示
时空限制:1000ms,128M
数据规模:
对于100%的数据: N ≤ 5000 , M ≤ 50000 N\le 5000,M\le 50000 N≤5000,M≤50000
样例说明:
如图,最优方案如下:
第一条流为 4 − > 3 4->3 4−>3,流量为 20 20 20,费用为 3 ∗ 20 = 60 3*20=60 3∗20=60。
第二条流为 4 − > 2 − > 3 4->2->3 4−>2−>3,流量为 20 20 20,费用为 ( 2 + 1 ) ∗ 20 = 60 (2+1)*20=60 (2+1)∗20=60。
第三条流为 4 − > 2 − > 1 − > 3 4->2->1->3 4−>2−>1−>3,流量为 10 10 10,费用为 ( 2 + 9 + 5 ) ∗ 10 = 160 (2+9+5)*10=160 (2+9+5)∗10=160。
故最大流量为50,在此状况下最小费用为 60 + 60 + 160 = 280 60+60+160=280 60+60+160=280。
故输出 50 280 50\ \ \ 280 50 280。
思路:
板子
代码:
#include
using namespace std;
#define in Read()
#define re register
inline char ch(){
static char buf[1<<21],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;
}
inline int in{
int s=0,f=1;char x;
for(x=getchar();x<'0'||x>'9';x=getchar()) if(x=='-') f=-1;
for( ;x>='0'&&x<='9';x=getchar()) s=(s<<1)+(s<<3)+(x&15);
return f==1?s:-s;
}
const int A=1e5+5;
const int INF=1e9;
int n,m,s,t;
int maxflow,mincost;
int head[A],tot_road=1;
struct Road{
int nex,to,flow,cost;
}road[4*A];
inline void ljb(int x,int y,int z,int c){
road[++tot_road]={head[x],y,z,c};head[x]=tot_road;
}
int dis[A];
bool ex[A];
inline bool spfa(){
fill(dis+1,dis+1+n,INF);
queue <int> q;
dis[s]=0,ex[s]=1;
q.push(s);
while(!q.empty()){
int x=q.front();q.pop();
ex[x]=0;
for(int y=head[x];y;y=road[y].nex){
int z=road[y].to,w=road[y].flow,c=road[y].cost;
if(w&&dis[z]>dis[x]+c){
dis[z]=dis[x]+c;
if(!ex[z]){
q.push(z);
ex[z]=1;
}
}
}
}
return dis[t]!=INF;
}
inline int DFS(int x,int flow){
if(x==t){
maxflow+=flow;
return flow;
}
int used=0;
ex[x]=1;
for(int y=head[x];y;y=road[y].nex){
int z=road[y].to,w=road[y].flow,c=road[y].cost;
if(!ex[z]&&w&&dis[z]==dis[x]+c){
int after=DFS(z,min(w,flow-used));
if(after){
used+=after;
mincost+=after*c;
road[y].flow-=after;
road[y^1].flow+=after;
}
}
if(used==flow) break;
}
ex[x]=0;
return used;
}
inline void MCMF(){
maxflow=mincost=0;
while(spfa()) DFS(s,INF);
return;
}
signed main(){
n=in,m=in,s=in,t=in;
while(m--){
int u=in,v=in,w=in,f=in;
ljb(u,v,w,f),ljb(v,u,0,-f);
}
MCMF();
printf("%d %d\n",maxflow,mincost);
return 0;
}