• 网络流 ek


    hdu3549 求最大流果题

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

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

    i^1 = i+1(i为奇数), i^1 = i-1(i为偶数)这样偶数位置放正边 奇数位置放反边 就可以快速找到边的逆边

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

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

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

    这个思路是ff方法 用bfs找增广路就是ek算法

    O(VE^2) 多半歇逼

    就这些

    #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
    ", ek(1, n));
        }
        return 0;
    }
    搞图论是没有用的,转行做数学题了hh
  • 相关阅读:
    GCC编绎详解
    GUN C/C++ __attribute__ 用法 转
    rust 参考的资料 转
    Eclipse环境安装rust
    GNU Debugger for Windows----GDB
    minGW cygwin gnuwin32
    tdm-gcc
    GNU tools
    The MinGW and mingw-w64 projects.----GCC
    crosstool-NG
  • 原文地址:https://www.cnblogs.com/DearDongchen/p/7546223.html
Copyright © 2020-2023  润新知