【HDU】3947 River Problem 最小费用最大流

来源:互联网 发布:拉萨有4g网络吗 编辑:程序博客网 时间:2024/06/10 18:09

传送门:【HDU】3947 River Problem


题目分析:

先设立超级源汇S、T。

首先对给定的树边建立反向边,然后从结点1开始遍历整棵树,如果到达叶子结点x,则建边(S,x,M,0)(其中M为大整数)。如果v不是叶子结点,且v的父节点为u,(u,v)的边权为w,则看x的子树内叶子结点的个数num,建边(v,u,num*M-w,0)。最后对所有的道具建边(u,v,c,w)。最后跑一遍最小费用最大流,如果流量等于以1为根结点的数的叶子节点个数,则输出cost,否则输出-1。

我们可以认为道具是弥补流量不足的情况的。只要容量较小的边的“坑”被道具边的流量完全“填上”最后汇点的流量才可能等于叶子节点个数*M。具体YY吧。。


代码如下:


#include <cstdio>#include <cstring>#include <algorithm>//#include <cmath>#include <queue>using namespace std ;  typedef long long LL ;  #define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define rev( i , a , b ) for ( int i = a ; i >= b ; -- i )#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )#define clr( a , x ) memset ( a , x , sizeof a )#define cpy( a , x ) memcpy ( a , x , sizeof a )const int MAXN = 2333 ;const int MAXE = 233333 ;const int INF = 0x3f3f3f3f ;const int M = 100000 ;struct Edge {int v , c , w , n ;Edge () {}Edge ( int v , int c , int w , int n ) : v ( v ) , c ( c ) , w ( w ) , n ( n ) {}} E[MAXE] , E2[MAXE] ;int H[MAXN] , D[MAXN] , cntE , cntE2 ;int d[MAXN] , cur[MAXN] , cap[MAXN] , vis[MAXN] ;int Q[MAXN] , head , tail ;int s , t ;int flow ;int cost ;int n , m ;int siz[MAXN] ;void clear () {cntE = cntE2 = 0 ;clr ( H , -1 ) ;clr ( D , -1 ) ;}void addedge ( int u , int v , int c , int w ) {E[cntE] = Edge ( v , c , +w , H[u] ) ;H[u] = cntE ++ ;E[cntE] = Edge ( u , 0 , -w , H[v] ) ;H[v] = cntE ++ ;}void add_tree_edge ( int u , int v , int c ) {E2[cntE2] = Edge ( v , 0 , c , D[u] ) ;D[u] = cntE2 ++ ;}int spfa () {head = tail = 0 ;clr ( d , INF ) ;clr ( vis , 0 ) ;Q[tail ++] = s ;d[s] = 0 ;cap[s] = INF ;cur[s] = -1 ;while ( head != tail ) {int u = Q[head ++] ;if ( head == MAXN ) head = 0 ;vis[u] = 0 ;for ( int i = H[u] ; ~i ; i = E[i].n ) {int v = E[i].v , c = E[i].c , w = E[i].w ;if ( c && d[v] > d[u] + w ) {d[v] = d[u] + w ;cap[v] = min ( cap[u] , c ) ;cur[v] = i ;if ( !vis[v] ) {vis[v] = 1 ;Q[tail ++] = v ;if ( tail == MAXN ) tail = 0 ;}}}}if ( d[t] == INF ) return 0 ;cost += d[t] * cap[t] ;flow += cap[t] ;for ( int i = cur[t] ; ~i ; i = cur[E[i ^ 1].v] ) {E[i].c -= cap[t] ;E[i ^ 1].c += cap[t] ;}return 1 ;}int mcmf () {cost = flow = 0 ;while ( spfa () ) ;return cost ;}void dfs ( int u ) {siz[u] = 0 ;bool leaf = 1 ;for ( int i = D[u] ; ~i ; i = E2[i].n ) {int v = E2[i].v ;leaf = 0 ;dfs ( v ) ;siz[u] += siz[v] ;addedge ( v , u , siz[v] * M - E2[i].w , 0 ) ;}if ( leaf ) addedge ( s , u , M , 0 ) , siz[u] = 1 ;}void solve () {int u , v , c , w , m ;clear () ;s = 0 ;t = 1 ;scanf ( "%d" , &n ) ;rep ( i , 1 , n ) {scanf ( "%d%d%d" , &u , &v , &w ) ;add_tree_edge ( v , u , w ) ;}dfs ( 1 ) ;scanf ( "%d" , &m ) ;while ( m -- ) {scanf ( "%d%d%d%d" , &u , &v , &c , &w ) ;addedge ( u , v , c , w ) ;}mcmf () ;//printf ( "%d\n" , flow ) ;if ( flow == siz[1] * M ) printf ( "%d\n" , cost ) ;else printf ( "-1\n" ) ;}int main () {int T , cas = 0 ;scanf ( "%d" , &T ) ;while ( T -- ) {printf ( "Case #%d: " , ++ cas ) ;solve () ;}return 0 ;}


0 0
原创粉丝点击