网络流 ek

Posted DearDongchen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流 ek相关的知识,希望对你有一定的参考价值。

hdu3549 求最大流果题

ek算法 先bfs出一条流 然后通过不断地添加增广路 得到最大流(证明在算法书上都有)

增加了一个流 就加反向边 允许程序通过走方向边的方式进行“回滚”

当i>=2时 i^1 = i+1(i为奇数), i^1 = i-1(i为偶数)这样从二开始 偶数位置放正边 计数位置放反边 就可以快速找到边的逆边

pre记录路径 具体是pre存到达当前点的边的序号

pre还顺便可以记录点的访问情况 省去了一个vis数组

每次bfs找到增广路径之后 从终点找到起点 找出最小的边权 就是这次增广增加的流

就这些

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 107, maxm = 1007, inf = 0x3f3f3f3f;
struct edge{
    int u, v, w, nxt;
    edge(){}
    edge(int u, int v, int w, int nxt):u(u), v(v), w(w), nxt(nxt){}
}e[2*maxm];
int cur, head[maxn], pre[maxn];
void addedge(int u, int v, int w){
    e[cur] = edge(u, v, w, head[u]);
    head[u] = cur++;
    e[cur] = edge(v, u, 0, head[v]);
    head[v] = cur++;
}
void init(){
    cur = 2;
    memset(head, -1, sizeof(head));
}
bool bfs(int st, int ed){
    queue<int>Q;
    memset(pre, -1, sizeof(pre));
    Q.push(st);
    while(!Q.empty()){
        int u = Q.front();
        Q.pop();
        if(u == ed)
            return true;
        for(int i = head[u]; ~i; i = e[i].nxt){
            int v = e[i].v, w = e[i].w;
            if(w && pre[v] == -1){
                pre[v] = i;
                Q.push(v);
            }
        }
    }
    return false;
}
int ek(int st, int ed){
    int ans = 0;
    while(bfs(st, ed)){
        int tmp = ed, det = inf;
        while(tmp != st){
            int edges = pre[tmp];
            det = min(det, e[edges].w);
            tmp = e[edges].u;
        }
        tmp = ed;
        while(tmp != st){
            int edges = pre[tmp];
            e[edges].w -= det;
            e[edges^1].w += det;
            tmp = e[edges].u;
        }
        ans += det;
    }
    return ans;
}
int main(){
    int t, kase = 0;
    scanf("%d", &t);
    while(t--){
        init();
        int n, m;
        scanf("%d%d", &n, &m);
        while(m--){
            int x, y, w;
            scanf("%d%d%d", &x, &y, &w);
            addedge(x, y, w);
        }
        printf("Case %d: ", ++kase);
        printf("%d\n", ek(1, n));
    }
    return 0;
}

 

以上是关于网络流 ek的主要内容,如果未能解决你的问题,请参考以下文章

网络(最大)流初步+二分图初步 (浅谈EK,Dinic, Hungarian method:]

网络最大流算法—EK算法

图论算法-网络最大流EK;Dinic

网络流 ek

算法学习笔记(8.1): 网络最大流算法 EK, Dinic, ISAP

网络流算法总汇(ek,dinic,isap)