Problem A: #102. 最小费用流
Time Limit: 5 Sec Memory Limit: 256 MBSubmit: 10 Solved: 5
[ Submit][ Status][ Web Board]
Description
这是一道模板题。
给定一个图,每条边有容量和费用,使用每条边的单位流量需要支付特定的费用。给定源点 1 和汇点n ,求图的最大流和最大流需要支付的最小费用。
Input
第一行两个整数 n 、m,表示有n 个点 m 条边。
从第二行开始的之后 m 行,每行四个整数si、ti、ci、wi 表示一条从si 到 ti 的边,容量为ci,单位流量需要支付的费用为 wi 。
Output
一行两个整数,分别表示最大流和最大流需要支付的最小费用。
Sample Input
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
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
Sample Output
6 24
HINT
1≤n≤400,0≤m≤15000 ,保证输入数据、中间结果以及答案在 32 位有符号整数范围内。
#include<cstdio>
#include<cstring>
const int maxn=1e4+10;
const int maxm=1e5+10;
const int maxt=2139062143;
inline int min_(int x,int y){return x<y?x:y;}
int n,m,s,t,nflow,nfee,flow,fee;
int a,b,c,d;
int h[maxn],hs=1;
int e_q[maxm],e_z[maxm],e_n[maxm],e_w[maxm],e_f[maxm];
int add(int q,int z,int k,int w,int f){e_q[k]=q,e_z[k]=z,e_n[k]=h[q],e_w[k]=w,e_f[k]=f,h[q]=k;}
int q[maxm],head,tail;
int w[maxn],p[maxn];
bool v[maxn];
int ap(int k,int v){
if(k==s) return v;
int ret=ap(e_q[p[k]],min_(v,e_w[p[k]]));
if(!e_f[p[k]^1]) add(k,e_q[p[k]],p[k]^1,0,-e_f[p[k]]);
e_w[p[k]]-=ret,e_w[p[k]^1]+=ret;
return ret;
}
void Mcmf(){
while(1){
memset(w,0x7f,sizeof(w));
memset(v,0,sizeof(v));
head=tail=w[s]=0;
q[head++]=s,v[s]=1;
while(head>tail){
a=q[tail++],v[a]=0;
for(int i=h[a];i;i=e_n[i])
if(0ll+e_f[i]+w[a]<w[e_z[i]]&&e_w[i]){
p[e_z[i]]=i;
w[e_z[i]]=e_f[i]+w[a];
if(!v[e_z[i]]) q[head++]=e_z[i],v[e_z[i]]=1;
}
}
if(w[t]==maxt) break;
nflow=ap(t,maxt);
flow+=nflow;
fee+=nflow*w[t];
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&a,&b,&c,&d);
++hs,add(a,b,hs,c,d),hs++;
}
Mcmf();
printf("%d %d\n",flow,fee);
return 0;
}