给定一张有向图,每条边都有一个容量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; }