zoukankan      html  css  js  c++  java
  • ZOJ-2364 Data Transmission 分层图阻塞流 Dinic+贪心预流

    题意:给定一个分层图,即只能够在相邻层次之间流动,给定了各个顶点的层次。要求输出一个阻塞流。

    分析:该题直接Dinic求最大流TLE了,网上说采用Isap也TLE,而最大流中的最高标号预流推进(HLPP)能够直接秒掉这一题。当然还有一种挽救的方式就是首先进行一次贪心预流,然后进行dinic。也是第一次听说还有贪心预流这回事,所以找了一份代码特地学习了一番。具体步骤如下:

    1.首先将所有节点按照层次进行排序,对每个节点有in[i]和out[i]两个属性,前者表示能够流入到该节点的流量,后者表示能够流出该节点的流量;
    2.从层次最低的节点(即源点)开始,设in[S] = inf,表示源点能够进入无限的流量,然后按照层次的递增来推流量,维护好每个节点的in和out值;
    3.从层次最高的节点(即汇点)开始,将所有节点的in都清空为0,设in[T] = inf,表示汇点能够收集无限的流量,然后从后往前计算出每条边实际能够流动的流量。

    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    const int N = 1505;
    const int M = 300005;
    const int inf = 0x3f3f3f3f;
    int n, m, L, SS, TT;
    int lv[N], rank[N], in[N], out[N];
    
    struct Edge {
        int v, c, nxt;
    }e[M<<1];
    int idx, head[N];
    int dis[N];
    char vis[N];
    queue<int>q;
    
    void insert(int a, int b, int c) {
        e[idx].v = b, e[idx].c = c;
        e[idx].nxt = head[a];
        head[a] = idx++;
    }
    
    bool bfs() {
        memset(dis, 0xff, sizeof (dis));
        memset(vis, 0, sizeof (vis));
        dis[SS] = 0, vis[SS] = 1;
        q.push(SS);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for (int i = head[u]; ~i; i = e[i].nxt) {
                int v = e[i].v, c = e[i].c;
                if (dis[v] == -1 && c) {
                    dis[v] = dis[u] + 1;
                    if (!vis[v]) {
                        vis[v] = 1;
                        q.push(v);
                    }
                }
            }
        }
        return dis[TT] != -1;
    }
    
    int dfs(int u, int flow) {
        if (u == TT) return flow;
        int tf = 0, f;
        for (int i = head[u]; ~i; i = e[i].nxt) {
            int v = e[i].v, c = e[i].c;
            if (dis[u]+1 == dis[v] && c && (f = dfs(v, min(flow-tf, c)))) {
                e[i].c -= f, e[i^1].c += f;
                tf += f;
                if (tf == flow) return tf;
            }
        }
        if (!tf) dis[u] = -1;
        return tf;
    }
    
    void dinic() {
        while (bfs()) {
            dfs(SS, inf);
        }
    }
    
    bool cmp(const int &a, const int &b) {
        return lv[a] < lv[b];
    }
    
    void greedy() {
        memset(in, 0, sizeof (in));
        memset(out, 0, sizeof (out));
        sort(rank+1, rank+1+n, cmp);
        in[SS] = inf;
        for (int i = 1; i <= n; ++i) {
            int u = rank[i];
            for (int j = head[u]; ~j; j = e[j].nxt) {
                int v = e[j].v, c = e[j].c;
                if (!(j & 1) && in[u] > out[u]) {
                    int f = min(c, in[u]-out[u]);
                    in[v] += f, out[u] += f;
                }
            }
        }
        memset(in, 0, sizeof (in));
        in[TT] = inf;
        for (int i = n; i >= 1; --i) {
            int v = rank[i];
            for (int j = head[v]; ~j; j = e[j].nxt) {
                int u = e[j].v, c = e[j^1].c;
                if (j & 1 && out[u] > in[u]) {
                    int f = min(c, min(out[u]-in[u], in[v]));
                    in[u] += f, in[v] -= f;
                    e[j].c += f, e[j^1].c -= f;
                }
            }
        }
    }
    
    int main() {
        int T;
        scanf("%d", &T);
        while (T--) {
            idx = 0;
            memset(head, 0xff, sizeof (head));
            scanf("%d %d %d", &n, &m, &L);
            for (int i = 1; i <= n; ++i) {
                rank[i] = i;
                scanf("%d", &lv[i]);
                if (lv[i] == 1) SS = i;
                else if (lv[i] == L) TT = i;
            }
            int a, b, c;
            for (int i = 0; i < m; ++i) {
                scanf("%d %d %d", &a, &b, &c);
                insert(a, b, c), insert(b, a, 0);
            }
            greedy(), dinic();
            for (int i = 0; i < m; ++i) {
                printf("%d
    ", e[i<<1|1].c);
            }
        }
        return 0;
    }
  • 相关阅读:
    静态查找表和动态查找表
    内存分配
    常用不等式
    考研线性代数(向量,线性方程组)
    考研线性代数(矩阵)
    考研线性代数(行列式)
    微积分常用思想方法小结
    bug修复集合(不定期更新)
    上下文对象及servletContext接口
    手动编解码解决get提交错误的问题
  • 原文地址:https://www.cnblogs.com/Lyush/p/3204099.html
Copyright © 2011-2022 走看看