ISAP 最大流 最小割 模板

虽然这道题用最小割没有做出来,但是这个板子还是很棒:

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define REV( i , a , b ) for ( int i = a - 1 ; i >= b ; -- i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define FOV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )
#define CPY( a , x ) memcpy ( a , x , sizeof a )
const int MAXN = 200005 ;
const int MAXQ = 800010 ;
const int MAXE = 800010 ;
const ll INF = 922337203685477580 ;

struct Edge {
    int v , n ;
    ll c ;
    Edge () {}
    Edge ( int v , ll c , int n ) : v ( v ) , c ( c ) , n ( n ) {}
} ;

struct Net {
    Edge E[MAXE];
    int H[MAXN] , cntE ;
    int d[MAXN] , num[MAXN] , cur[MAXN] , pre[MAXN] ;
    int Q[MAXQ] , head , tail ;
    int s , t , nv ;
    int n , m ;
    ll flow ;

    int deg[MAXN] ;

    inline void init () {
        cntE = 0 ;
        CLR ( H , -1 ) ;
        int i;
        for(i=0; i <= n+3 ; i++)    H[i] = -1;
    }

    inline void addedge ( int u , int v , ll c ) {
        E[cntE] = Edge ( v , c , H[u] ) ;
        H[u] = cntE ++ ;
        E[cntE] = Edge ( u , c , H[v] ) ;
        H[v] = cntE ++ ;
    }

    inline void rev_bfs () {
        CLR ( d , -1 ) ;
        int i;
        for(i=0; i <= n+3 ; i++)    d[i] = -1;
        CLR ( num , 0 ) ;
        head = tail = 0 ;
        Q[tail ++] = t ;
        d[t] = 0 ;
        num[d[t]] = 1 ;
        while ( head != tail ) {
            int u = Q[head ++] ;
            for ( int i = H[u] ; ~i ; i = E[i].n ) {
                int v = E[i].v ;
                if ( ~d[v] )
                    continue ;
                d[v] = d[u] + 1 ;
                num[d[v]] ++ ;
                Q[tail ++] = v ;
            }
        }
    }

    inline ll ISAP () {
        CPY ( cur , H ) ;
        rev_bfs () ;
        flow = 0 ;
        int u = pre[s] = s ;
        while ( d[s] < nv ) {
            if ( u == t ) {
                ll f = INF , pos ;
                for ( int i = s ; i != t ; i = E[cur[i]].v )
                    if ( f > E[cur[i]].c ) {
                        f = E[cur[i]].c ;
                        pos = i ;
                    }
                for ( int i = s ; i != t ; i = E[cur[i]].v ) {
                    E[cur[i]].c -= f ;
                    E[cur[i] ^ 1].c += f ;
                }
                flow += f ;
                u = pos ;
            }
            for ( int &i = cur[u] ; ~i ; i = E[i].n )
                if ( E[i].c && d[u] == d[E[i].v] + 1 )
                    break ;
            if ( ~cur[u] ) {
                pre[E[cur[u]].v] = u ;
                u = E[cur[u]].v ;
            } else {
                if ( 0 == ( -- num[d[u]] ) )
                    break ;
                int mmin = nv ;
                for ( int i = H[u] ; ~i ; i = E[i].n )
                    if ( E[i].c && mmin > d[E[i].v] ) {
                        cur[u] = i ;
                        mmin = d[E[i].v] ;
                    }
                d[u] = mmin + 1 ;
                num[d[u]] ++ ;
                u = pre[u] ;
            }
        }
        return flow ;
    }

    inline void solve () {
        int u , v ;
        ll c ;
        init () ;
        CLR ( deg , 0 ) ;
        s = 0 ;
        t = n ;
        nv = t;
        REP ( i , 1 , n ) {
            scanf ( "%d%d%lld" , &u , &v , &c ) ;
            addedge ( u  , v  , c ) ;
            ++ deg[u] ;
            ++ deg[v] ;
        }
        printf ( "%lld\n" , ISAP () ) ;
    }
} x ;

int main () {
//    while ( ~scanf ( "%d" , &x.n ) && ( x.n ) ) {
//        x.m = x.n - 1;
    scanf("%d",&x.n);
    x.solve () ;
//    }

    return 0 ;
}

猜你喜欢

转载自www.cnblogs.com/zinyy/p/9139094.html