传说有一个EK算法,时间复杂度是O(n*m^2)的,我想学这个,然后被大家给阻止了,因为有一个比较棒的dinic算法,时间复杂度是O(n^2*m)的。
网络流大概是这样的问题:
一个水的发源点S(可以提供无限量的水),一个汇集点T,水从发源点要流过许多容量一定的管道后,最后回到汇集点,求最大能流多少水。
想一想也知道,最大流量跟管子的容量肯定有关,并且想达到最大能流的水量,必然有某几个管道已经里面装满了水。
引入概念:
容量网络:图G(V,E)为有向网络,在V中指定一个源点和一个汇点,流量从源点出发经过有向网络流向汇点。对于每一条有向边有权值C,称作弧的容量。有向边称为弧。这样的有向网络称为容量网络。(可以粗略理解为现在我们面临的处境(问题描述))
残留网络:假设一条边容量为A,流量为B,那残余容量就是A-B,而以残余容量为边的有向网络就是残留网络。
饱和:容量等于流量。
零流:流量为0.
前(后)向弧:在S—-T的路径上与路径相同(反)的有向边。
增广路:就是S—-T的一条可以扩充流量的路径。(也就是说前向弧)
模版大概是这样:
bool bfs(){
int h = 1, t = 1;CLR(dep,-1);
dep[q[1] = S ] = 0;
while(h <= t){int x = q[h ++ ] ;RepG(i,x)if(fl && dep[v] == -1)dep[q[++ t] = v] = dep[x] + 1;}
return dep[T] > 0;
}
int dfs(int x,int f){
if(x == T)return f;
int s = 0,ff;
RepG(i,x)if(f && fl && dep[v] = dep[x] + 1 && (ff = dfs(v,min (fl,f))))s += ff, fl -= ff,vfl += ff,f -= ff;
if(!s)dep[x] = -1;
return s;
}
void save(int u,int vv,int f){edge[cnt].f = f;edge[cnt].next = head[u];edge[cnt].to = vv;head[u] = cnt ++;}
int maxflow(){int s = 0 ; for(;bfs();s += dfs(S,inf));return s;}