[ZJOI2010]network 网络扩容

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

你可能感兴趣的:(C++,c,F#,C#,J#)