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\n", hlpp.hlpp(s, t));
    }
    return 0;
}
上一篇:@codeforces - 1097G@ Vladislav and a Great Legend


下一篇:GCN论文源码(pytorch)超级详细注释讲解!