zoukankan      html  css  js  c++  java
  • HDU 4280 Island Transport(HLPP板子)题解

    题意:

    求最大流

    思路:

    (1e5)条边,偷了一个超长的(HLPP)板子。复杂度(n^2 sqrt{m})。但通常在随机情况下并没有isap快。

    板子:

    template<class T = int>
    struct HLPP{
        const int MAXN = 1e5 + 5;
        const T INF = 0x3f3f3f3f;
        struct edge{
            int to, rev;
            T f;
        };
        vector<edge> adj[maxn];
        deque<int> lst[maxn];
        vector<int> gap[maxn];
        T excess[maxn];
        int highest, height[maxn], cnt[maxn], ptr[maxn], work, N;
    
        void addEdge(int u, int v, int f, bool isdirected = true){
            adj[u].push_back({v, adj[v].size(), f});
            adj[v].push_back({u, adj[u].size() - 1, isdirected? 0 : f});
        }
    
        void clear(int n){
            N = n;
            for(int i = 0; i <= n; i++){
                adj[i].clear(), lst[i].clear();
                gap[i].clear();
            }
        }
    
        void upHeight(int v, int nh){
            ++work;
            if(height[v] != N) --cnt[height[v]];
            height[v] = nh;
            if(nh == N) return;
            cnt[nh]++, highest = nh;
            gap[nh].push_back(v);
            if(excess[v] > 0){
                lst[nh].push_back(v);
                ++ptr[nh];
            }
        }
    
        void glovalRelabel(int s, int t){
            work = 0;
            fill(height, height + N + 1, N);
            fill(cnt, cnt + N + 1, 0);
            for(int i = 0; i <= highest; i++){
                lst[i].clear();
                gap[i].clear();
                ptr[i] = 0;
            }
            height[t] = 0;
            queue<int> q({t});
            while(!q.empty()){
                int v = q.front();
                q.pop();
                for(auto &e : adj[v])
                if(height[e.to] == N && adj[e.to][e.rev].f > 0){
                    q.push(e.to);
                    upHeight(e.to, height[v] + 1);
                }
                highest = height[v];
            }
        }
        void push(int v, edge& e){
            if(excess[e.to] == 0){
                lst[height[e.to]].push_back(e.to);
                ++ptr[height[e.to]];
            }
            T df = min(excess[v], e.f);
            e.f -= df;
            adj[e.to][e.rev].f += df;
            excess[v] -= df;
            excess[e.to] += df;
        }
        void discharge(int v){
            int nh = N;
            for(auto &e : adj[v]){
                if(e.f > 0){
                    if(height[v] == height[e.to] + 1){
                        push(v, e);
                        if(excess[v] <= 0) return;
                    }
                    else{
                        nh = min(nh, height[e.to] + 1);
                    }
                }
            }
            if(cnt[height[v]] > 1){
                upHeight(v, nh);
            }
            else{
                for(int i = height[v]; i < N; i++){
                    for(auto j : gap[i]) upHeight(j, N);
                    gap[i].clear(); ptr[i] = 0;
                }
            }
        }
    
        T hlpp(int s, int t){
            fill(excess, excess + N + 1, 0);
            excess[s] = INF, excess[t] = -INF;
            glovalRelabel(s, t);
            for(auto &e : adj[s]) push(s, e);
            for(; highest >= 0; -- highest){
                while(lst[highest].size()){
                    int v = lst[highest].back();
                    lst[highest].pop_back();
                    discharge(v);
                    if(work > 4 * N) glovalRelabel(s, t);
                }
            }
            return excess[t] + INF;
        }
    
    };
    
    
    int read() {
        int f = 1, x = 0; char ch = getchar();
        while(! isdigit(ch)) {if(ch == '-' ) f = -f; ch = getchar();}
        while(isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
        return x * f;
    }
    
    HLPP<int> hlpp;
    
    //hlpp.clear(n)
    
    

    代码:

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdlib>
    #include <string>
    #include <cstdio>
    #include <queue>
    #define  isdigit(a)     (a>='0' && a<='9')
    typedef long long LL;
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int maxn = 2e5+5;
    
    template<class T = int>
    struct HLPP{
        const int MAXN = 1e5 + 5;
        const T INF = 0x3f3f3f3f;
        struct edge{
            int to, rev;
            T f;
        };
        vector<edge> adj[maxn];
        deque<int> lst[maxn];
        vector<int> gap[maxn];
        T excess[maxn];
        int highest, height[maxn], cnt[maxn], ptr[maxn], work, N;
    
        void addEdge(int u, int v, int f, bool isdirected = true){
            adj[u].push_back({v, adj[v].size(), f});
            adj[v].push_back({u, adj[u].size() - 1, isdirected? 0 : f});
        }
    
        void clear(int n){
            N = n;
            for(int i = 0; i <= n; i++){
                adj[i].clear(), lst[i].clear();
                gap[i].clear();
            }
        }
    
        void upHeight(int v, int nh){
            ++work;
            if(height[v] != N) --cnt[height[v]];
            height[v] = nh;
            if(nh == N) return;
            cnt[nh]++, highest = nh;
            gap[nh].push_back(v);
            if(excess[v] > 0){
                lst[nh].push_back(v);
                ++ptr[nh];
            }
        }
    
        void glovalRelabel(int s, int t){
            work = 0;
            fill(height, height + N + 1, N);
            fill(cnt, cnt + N + 1, 0);
            for(int i = 0; i <= highest; i++){
                lst[i].clear();
                gap[i].clear();
                ptr[i] = 0;
            }
            height[t] = 0;
            queue<int> q({t});
            while(!q.empty()){
                int v = q.front();
                q.pop();
                for(auto &e : adj[v])
                if(height[e.to] == N && adj[e.to][e.rev].f > 0){
                    q.push(e.to);
                    upHeight(e.to, height[v] + 1);
                }
                highest = height[v];
            }
        }
        void push(int v, edge& e){
            if(excess[e.to] == 0){
                lst[height[e.to]].push_back(e.to);
                ++ptr[height[e.to]];
            }
            T df = min(excess[v], e.f);
            e.f -= df;
            adj[e.to][e.rev].f += df;
            excess[v] -= df;
            excess[e.to] += df;
        }
        void discharge(int v){
            int nh = N;
            for(auto &e : adj[v]){
                if(e.f > 0){
                    if(height[v] == height[e.to] + 1){
                        push(v, e);
                        if(excess[v] <= 0) return;
                    }
                    else{
                        nh = min(nh, height[e.to] + 1);
                    }
                }
            }
            if(cnt[height[v]] > 1){
                upHeight(v, nh);
            }
            else{
                for(int i = height[v]; i < N; i++){
                    for(auto j : gap[i]) upHeight(j, N);
                    gap[i].clear(); ptr[i] = 0;
                }
            }
        }
    
        T hlpp(int s, int t){
            fill(excess, excess + N + 1, 0);
            excess[s] = INF, excess[t] = -INF;
            glovalRelabel(s, t);
            for(auto &e : adj[s]) push(s, e);
            for(; highest >= 0; -- highest){
                while(lst[highest].size()){
                    int v = lst[highest].back();
                    lst[highest].pop_back();
                    discharge(v);
                    if(work > 4 * N) glovalRelabel(s, t);
                }
            }
            return excess[t] + INF;
        }
    
    };
    
    
    int read() {
        int f = 1, x = 0; char ch = getchar();
        while(! isdigit(ch)) {if(ch == '-' ) f = -f; ch = getchar();}
        while(isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
        return x * f;
    }
    
    HLPP<int> hlpp;
    
    int main() {
        int T;
        scanf("%d", &T);
        while(T--) {
            int n, m;
            scanf("%d%d", &n, &m);
            int x, y, s, t;
            int startX = inf, endX = -inf;
            for(int i = 1; i <= n; ++i) {
                x = read(), y = read();
                if(x < startX)  s = i, startX = x;
                if(x > endX)   t = i, endX = x;
            }
            int u, v, f;
            hlpp.clear(n);
            for(int i = 1; i <= m; ++i) {
                u = read(), v = read(), f = read();
                hlpp.addEdge(u, v, f, false);
            }
    
            printf("%d
    ", hlpp.hlpp(s, t));
        }
        return 0;
    }
    
    
  • 相关阅读:
    Android Studio在项目中添加assets资源目录
    Android Studio向项目中导入jar包的方法
    Android Studio 配置 androidAnnotations框架详细步骤
    Android退出所有Activity最优雅的方式
    Android数据存储之SQLite使用
    Android数据存储之SharedPreferences使用
    三种实现Android主界面Tab的方式
    Android热门网络框架Volley详解
    Android必学之数据适配器BaseAdapter
    23种设计模式UML图
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11329288.html
Copyright © 2011-2022 走看看