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 ;
}

原文地址:https://www.cnblogs.com/zinyy/p/9139094.html

时间: 2024-07-29 05:14:27

ISAP 最大流 最小割 模板的相关文章

最大流-最小割 MAXFLOW-MINCUT ISAP

简单的叙述就不必了. 对于一个图,我们要找最大流,对于基于增广路径的算法,首先必须要建立反向边. 反向边的正确性: 我努力查找了许多资料,都没有找到理论上关于反向边正确性的证明. 但事实上,我们不难理解,对于每条反向边,我们流过它相当于撤销了一条正向边的流量. 并且它是必须的: 而且从理论上,我们在加入反向边之后得到的最大流,我们从残余网络考虑. 我们要认识到,反向边不会使最大流流量减少,这是很显然的.有flow<=flow'. 接下来我们考虑所有点的流量是否可以只用正向边得到. 并且我们考察汇

最小割模板 zoj2753

最大流 == 最小割 ///无向图 求最小割 模板 节点编号从 1 开始 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; int n,m; int cnt = 0; int mp[510][510] ; int v[510] ,dis[510] ,vis[510] ; int Stoer_Wagner(int

zoj3792--Romantic Value(最大流+最小割,求解割边)

Romantic Value Time Limit: 2 Seconds      Memory Limit: 65536 KB Farmer John is a diligent man. He spent a lot of time building roads between his farms. From his point of view, every road is romantic because the scenery along it is very harmonious an

bzoj1412-网络流最小割

狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆.可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已.所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养. 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变

hdu 3987 Harry Potter and the Forbidden Forest【网路流最小割模型】

Harry Potter and the Forbidden Forest Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1549    Accepted Submission(s): 528 Problem Description Harry Potter notices some Death Eaters try to slip

UVA 11248 Frequency Hopping (最大流+最小割)

题意:与正常的网络流一样,不过给定的第一行的最后一个数C的意思是能能否在给定的图里求出修改某一条边或者不修改某一条边是的这个图的流变成C,如果没修改就能有C,那么输出possible,通过修改能得到C输出possible+能修改的边集合,否则输出no possible 思路:(自己的是死暴力方法,直接爆了,想了很多法子都来不起,最后参照白书的思路来起了)可以先求出最大流,然后求出最小割里的弧,依次修改最小割里的弧,看能求出的最大流是否大于C PS:不优化的话很容易超时,第一个优化是把第一次求得得

最大流, 最小割问题及算法实现

最大流(MaxFlow)问题 给定指定的一个有向图,其中有两个特殊的点源S(Sources)和汇T(Sinks),每条边有指定的容量(Capacity),求满足条件的从S到T的最大流(MaxFlow). 想象一条多条不同水流量的水管组成的网络, s为供水广, t为水用户, 最大流问题就是找到能够在s到t流通的最大水流量 一个流是最大流当且仅当其残存网络不包含任何增广路径(里面的名称在后面有详细解释) 流(Flow)的基本性质 设$C_{uv}$代表边u到v最大允许流量(Capacity), $f

【图割】opencv中构建图和最大流/最小割的源码解读

#include <vector> using namespace std; #define MIN(a,b) (((a)<(b))?(a):(b)) typedef unsigned char uchar; template <class TWeight> class GCGraph { public: GCGraph(); GCGraph(unsigned int vtxCount, unsigned int edgeCount); ~GCGraph(); void cr

UVA-11248 Frequency Hopping (最大流+最小割)

题目大意:给一张网络,问是否存在一条恰为C的流.若不存在,那是否存在一条弧,使得改动这条弧的容量后能恰有为C的流? 题目分析:先找出最大流,如果最大流不比C小,那么一定存在一条恰为C的流.否则,找出最小割集,然后枚举每一条弧改动其容量,看是否存在恰为C的流. 代码如下: # include<iostream> # include<cstdio> # include<cmath> # include<string> # include<vector>