给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求:
1、 在不扩容的情况下,1到N的最大流;
2、 将1到N的最大流增加K所需的最小扩容费用。
求出最大流后,残余网络的流量不变,费用改为 0. 对原图的每一条边,对应增加一条流量为 k,费用为 w 的边,再增加一个源,源到 1 的流量为 k,费用为 0。求最小费用最大流,即为第二问答案。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define min(a,b) ( (a)< (b)? (a): (b) )
#define inf 0x7fffffff
int const N= 1010, M= 5010;
int n, m, k, cnt, S, T;
int dist[N][N];
struct Edge{
int flow, cost, adj;
Edge* next;
}tb[M<<2];
Edge* mat[N], *Pre[N];
inline Edge* reserve( Edge* p ){
return tb+ ( (p- tb)^ 1 );
}
inline void add( int u, int v, int c, int w ){
++cnt;
tb[cnt].adj= v; tb[cnt].flow= c; tb[cnt].cost= w;
tb[cnt].next= mat[u]; mat[u]= tb+ cnt;
++cnt;
tb[cnt].adj= u; tb[cnt].flow= 0; tb[cnt].cost= -w;
tb[cnt].next= mat[v]; mat[v]= tb+ cnt;
}
int que[M<<2], ht[N], flag[N], path[N], head, tail;
int bfs(){
que[0]= S; head= 0; tail= 0;
for( int i= 0; i<= n; ++i ) ht[i]= -1; ht[S]= 0;
while( head<= tail ){
int u= que[head++];
for( Edge* p= mat[u]; p; p= p->next )
if( ht[p->adj]== -1 && p->flow ){
ht[p->adj]= ht[u]+ 1;
que[++tail]= p->adj;
}
}
return ht[T]!= -1;
}
int dfs( int u, int flow ){
if( u== T ) return flow;
int tf= 0, f;
for( Edge* p= mat[u]; p; p= p->next )
if( ht[p->adj]== ht[u]+ 1 && p->flow && flow> tf &&
( f= dfs( p->adj, min( p->flow, flow- tf ) ) ) ){
reserve( p )->flow+= f;
p->flow-= f;
tf+= f;
}
if( tf== 0 ) ht[u]= -1;
return tf;
}
int spfa(){
for( int i= 0; i<= n; ++i ) {
ht[i]= inf; flag[i]= 0; }
que[0]= S; head= tail= 0;
path[S]= S; flag[S]= 1; ht[S]= 0;
while( head<= tail ){
int u= que[head++]; flag[u]= 0;
for( Edge* p= mat[u]; p; p= p->next )
if( p->flow && ht[u]+ p->cost< ht[p->adj] ){
ht[p->adj]= ht[u]+ p->cost;
Pre[p->adj]= p; path[p->adj]= u;
if( flag[p->adj]== 0 ){
flag[p->adj]= 1;
que[++tail]= p->adj;
}
}
}
return ht[T]!= inf;
}
int min_cost(){
int res= 0;
while( spfa() ){
int tf= inf, tmp= path[T];
while( tmp!= S ){
tf= min( Pre[tmp]->flow, tf );
tmp= path[tmp];
}
tmp= path[T];
while( tmp!= S ){
Pre[tmp]->flow-= tf;
reserve( Pre[tmp] )->flow+= tf;
tmp= path[tmp];
}
res+= ht[T]* tf;
}
return res;
}
int main(){
while( scanf("%d%d%d",&n,&m,&k)!= EOF ){
int u, v, c, w;
cnt= -1;
for( int i= 0; i<= n+ 1; ++i ) mat[i]= 0;
for( int i= 0; i<= n; ++i )
for( int j= 0; j<= n; ++j ) dist[i][j]= -1;
S= 1; T= n;
for( int i= 0; i< m; ++i ){
scanf("%d%d%d%d", &u, &v, &c, &w );
add( u, v, c, 0 );
dist[u][v]= w;
}
int ans= 0;
while( bfs() ) ans+= dfs( S, 0x7fffffff );
for( int i= 1; i<= n; ++i )
for( int j= 1; j<= n; ++j )
if( dist[i][j]!= -1 ) add( i, j, k, dist[i][j] );
S= T+ 1;
add( S, 1, k, 0 );
int res= min_cost();
printf("%d %d\n", ans, res );
}
return 0;
}