Solution Set【2023.12.5】

[AHOI2009] 最小割

首先考虑如何处理可行边,对于边 \(\left(u, v\right)\),其为可行边与同时满足下列两个条件互为充要条件:

  • \(c_f(u, v) = 0\)
  • \(G_f\) 中不存在路径 \(u \rightarrow v\)

首先可以发现若存在 \(G_f\) 使得 \(c_f(u, v) > 0\),那么一定不会割这条边。

\(G_f\) 中存在路径 \(u \rightarrow v\),那么可以通过将边 \(\left(u, v\right)\) 的一小部分流量通过 \(G_f\) 中存在路径 \(u \rightarrow v\) 传递。这样之后有 \(c_f(u, v) > 0\),那么一定不会割这条边。

考虑在可行边的基础上添加什么条件才可以使得边为必须边。

可以发现,若对于可行边 \(\left(u, v\right)\),若在 \(G_f\) 上不存在路径使得 \(S \rightarrow u\),那么在 \(G\) 的任意一条路径 \(S \rightarrow u\) 上,均存在令一条可行边,因此边 \(\left(u, v\right)\) 不是必须边。

所以可行边 \(\left(u, v\right)\) 是必须边当且仅当 \(G_f\) 上存在路径 \(S \rightarrow u\) 和路径 \(v \rightarrow T\)

可以发现因为 \(c_f(u, v) = 0\),所以有 \(c_f(v, u) > 0\),即边 \(\left(v, u\right) \in G_f\),所以在 \(G_f\) 上存在路径 \(u \rightarrow v\) 等价于 \(u, v\)\(G_f\) 上位于同一个强连通分量中。同理 \(G_f\) 上存在路径 \(S \rightarrow u\) 和路径 \(v \rightarrow T\) 等价于 \(u\)\(S\) 在同一个强连通分量中且 \(v\)\(T\) 在同一个强连通分量中。

Code
#include <bits/stdc++.h>

typedef long long valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<bool> bitset;
typedef std::tuple<valueType, valueType, valueType> ValueTuple;
typedef std::vector<ValueTuple> TupleVector;

class Dinic {
private:
    struct Edge {
    public:
        typedef std::vector<Edge> container;
        typedef container::iterator iterator;

        valueType to;
        valueType cap;
        valueType flow;
        iterator pair;

        Edge() : to(-1), cap(-1), flow(-1), pair(){};

        Edge(valueType to, valueType cap, iterator pair = iterator()) : to(to), cap(cap), flow(0), pair(pair){};

        bool full() const {
            return flow == cap;
        }
    };

    typedef std::vector<ValueVector> Graph;
    typedef std::vector<ValueVector::iterator> IterVector;

    valueType N, M;
    Edge::container edges;
    Graph G;
    ValueVector depth;
    IterVector start;
    ValueVector belong;
    bitset inStack;
    ValueVector dfn, low;
    std::stack<valueType> stack;
    bool Initialized;

public:
    explicit Dinic(valueType N, valueType M) : N(N), M(M), edges((M << 1) + 10), G(N + 1), depth(N + 1, 0), start(N + 1), belong(N + 1, 0), inStack(N + 1, false), dfn(N + 1, 0), low(N + 1, 0), Initialized(false){};

    void addEdge(valueType from, valueType to, valueType cap, valueType id) {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: addEdge after init");

        edges[id << 1] = Edge(to, cap, std::next(edges.begin(), id << 1 | 1));
        edges[id << 1 | 1] = Edge(from, 0, std::next(edges.begin(), id << 1));
        G[from].emplace_back(id << 1);
        G[to].emplace_back(id << 1 | 1);
    }

    void init() {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: init twice");

        Initialized = true;

        std::fill(depth.begin(), depth.end(), 0);

        for (valueType i = 1; i <= N; ++i)
            start[i] = G[i].begin();
    }

    void reset() {
        if (__builtin_expect(!Initialized, false))
            throw std::runtime_error("Dinic: reset before init");

        for (valueType i = 1; i <= N; ++i)
            for (auto &iter : G[i])
                edges[iter].flow = 0;

        std::fill(depth.begin(), depth.end(), 0);

        Initialized = false;
    }

    valueType maxFlow(valueType S, valueType T) {
        if (__builtin_expect(!Initialized, false))
            throw std::runtime_error("Dinic: maxFlow before init");

        valueType result = 0;

        while (bfs(S, T)) {
            IterVector begin = start;

            result += dfs(S, T, std::numeric_limits<valueType>::max(), begin);
        }

        for (valueType i = 1; i <= N; ++i)
            if (!dfn[i])
                tarjan(i);

        return result;
    }

    valueType scc(valueType n) const {
        return belong[n];
    }

    bool full(valueType m) const {
        return edges[m].full();
    }

private:
    bool bfs(valueType S, valueType T) {
        std::fill(depth.begin(), depth.end(), 0);

        std::queue<valueType> Q;

        Q.push(S);
        depth[S] = 1;

        while (!Q.empty()) {
            valueType const u = Q.front();

            Q.pop();

            for (auto const &iter : G[u]) {
                auto const &e = edges[iter];
                if ((e.cap > e.flow) && (!depth[e.to])) {
                    depth[e.to] = depth[u] + 1;
                    Q.push(e.to);
                }
            }
        }

        return depth[T] > 0;
    }

    valueType dfs(valueType u, valueType T, valueType flow, IterVector &Begin) {
        if (u == T || flow == 0)
            return flow;

        valueType result = 0;

        for (auto &iter = Begin[u]; iter != G[u].end(); ++iter) {
            auto e = std::next(edges.begin(), *iter);
            if (e->cap > e->flow && depth[e->to] == depth[u] + 1) {
                valueType const f = dfs(e->to, T, std::min(flow - result, e->cap - e->flow), Begin);

                e->flow += f;
                e->pair->flow -= f;

                result += f;

                if (result == flow)
                    return flow;
            }
        }

        return result;
    }

    void tarjan(valueType x) {
        static valueType dfsCount = 0, sccCount = 0;

        inStack[x] = true;
        low[x] = dfn[x] = ++dfsCount;
        stack.push(x);

        for (auto const &iter : G[x]) {
            auto e = std::next(edges.begin(), iter);

            if (e->full())
                continue;

            if (!dfn[e->to]) {
                tarjan(e->to);

                low[x] = std::min(low[x], low[e->to]);
            } else if (inStack[e->to]) {
                low[x] = std::min(low[x], dfn[e->to]);
            }
        }

        if (dfn[x] == low[x]) {
            ++sccCount;

            valueType y;

            do {
                y = stack.top();

                stack.pop();

                inStack[y] = false;

                belong[y] = sccCount;
            } while (y != x);
        }
    }
};

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    valueType N, M, S, T;

    std::cin >> N >> M >> S >> T;

    Dinic dinic(N, M);

    TupleVector G;

    G.reserve(M);

    for (valueType i = 1; i <= M; ++i) {
        valueType u, v, w;

        std::cin >> u >> v >> w;

        G.emplace_back(u, v, w);

        dinic.addEdge(u, v, w, i);
    }

    dinic.init();

    dinic.maxFlow(S, T);

    for (valueType i = 0; i < M; ++i) {
        valueType const id = i + 1;

        auto const &[u, v, w] = G[i];

        bool A = dinic.full(id << 1) && dinic.scc(u) != dinic.scc(v);

        bool B = A && dinic.scc(S) == dinic.scc(u) && dinic.scc(T) == dinic.scc(v);

        std::cout << A << ' ' << B << '\n';
    }

    std::cout << std::flush;

    return 0;
}

【模板】最小割树(Gomory-Hu Tree)

通过一些证明可以得出结论:最小割不交叉。

因此在点集中任选两点 \(S, T\),我们可以在整个网络中求出其最小割,并在新树中建边 \((S, T)\),边权为最小割的容量,然后将点集划分为两个子集后继续递归划分。

可以发现一共需要求 \(\mathcal{O}(N)\) 次最小割,因此复杂度为 \(\mathcal{O}(N^3M)\)

由于 \(N\) 的值很小,故在完成建树后可以将所有路径的最小值预处理出来后 \(\mathcal{O}(1)\) 回答所有询问。

Code
#include <bits/stdc++.h>

typedef long long valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<ValueVector> ValueMatrix;
typedef std::pair<valueType, valueType> ValuePair;
typedef std::vector<ValuePair> PairVector;
typedef std::vector<PairVector> PairMatrix;

class Dinic {
private:
    struct Edge {
    public:
        typedef std::list<Edge> container;
        typedef container::iterator iterator;

        valueType to;
        valueType cap;
        valueType flow;
        iterator pair;

        Edge() : to(-1), cap(-1), flow(-1), pair(){};

        Edge(valueType to, valueType cap, iterator pair = iterator()) : to(to), cap(cap), flow(0), pair(pair){};
    };

    typedef std::vector<Edge::container> Graph;
    typedef std::vector<Edge::iterator> IterVector;

    valueType N;
    Graph G;
    ValueVector depth;
    IterVector start;
    bool Initialized;

public:
    explicit Dinic(valueType N) : N(N), G(N + 1), depth(N + 1, 0), start(N + 1), Initialized(false){};

    void addEdge(valueType x, valueType y, valueType cap) {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: addEdge after init");

        G[x].emplace_back(y, cap);
        G[y].emplace_back(x, cap);
        G[x].back().pair = std::prev(G[y].end());
        G[y].back().pair = std::prev(G[x].end());
    }

    void init() {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: init twice");

        Initialized = true;

        std::fill(depth.begin(), depth.end(), 0);

        for (valueType i = 1; i <= N; ++i)
            start[i] = G[i].begin();
    }

    void reset() {
        for (valueType i = 1; i <= N; ++i)
            for (auto &iter : G[i])
                iter.flow = 0;

        std::fill(depth.begin(), depth.end(), 0);

        Initialized = false;
    }

    valueType maxFlow(valueType S, valueType T) {
        if (__builtin_expect(!Initialized, false))
            throw std::runtime_error("Dinic: maxFlow before init");

        valueType result = 0;

        while (bfs(S, T)) {
            IterVector begin = start;

            result += dfs(S, T, std::numeric_limits<valueType>::max(), begin);
        }

        return result;
    }

    bool reachable(valueType n) const {
        return depth[n] > 0;
    }

private:
    bool bfs(valueType S, valueType T) {
        std::fill(depth.begin(), depth.end(), 0);

        std::queue<valueType> Q;

        Q.push(S);
        depth[S] = 1;

        while (!Q.empty()) {
            valueType const u = Q.front();

            Q.pop();

            for (auto const &e : G[u]) {
                if ((e.cap > e.flow) && (!depth[e.to])) {
                    depth[e.to] = depth[u] + 1;
                    Q.push(e.to);
                }
            }
        }

        return depth[T] > 0;
    }

    valueType dfs(valueType u, valueType T, valueType flow, IterVector &Begin) {
        if (u == T || flow == 0)
            return flow;

        valueType result = 0;

        for (auto &e = Begin[u]; e != G[u].end(); ++e) {
            if (e->cap > e->flow && depth[e->to] == depth[u] + 1) {
                valueType const f = dfs(e->to, T, std::min(flow - result, e->cap - e->flow), Begin);

                e->flow += f;
                e->pair->flow -= f;

                result += f;

                if (result == flow)
                    return flow;
            }
        }

        return result;
    }
};

void solve(ValueVector const &V, PairMatrix &G, Dinic &dinic) {
    if (V.size() < 2)
        return;

    valueType const S = V.front(), T = V.back();

    dinic.reset();

    dinic.init();

    valueType const weight = dinic.maxFlow(S, T);

    G[S].emplace_back(T, weight);
    G[T].emplace_back(S, weight);

    ValueVector A, B;

    for (auto const &iter : V) {
        if (dinic.reachable(iter))
            A.emplace_back(iter);
        else
            B.emplace_back(iter);
    }

    solve(A, G, dinic);
    solve(B, G, dinic);
}

void dfs(valueType x, valueType from, PairMatrix const &G, ValueVector &dist) {
    for (auto const &[to, weight] : G[x]) {
        if (to == from)
            continue;

        dist[to] = std::min(dist[x], weight);

        dfs(to, x, G, dist);
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    valueType N, M;

    std::cin >> N >> M;

    // ++N;

    Dinic dinic(N);

    for (valueType i = 0; i < M; ++i) {
        valueType u, v, w;

        std::cin >> u >> v >> w;

        // ++u;
        // ++v;

        dinic.addEdge(u, v, w);
    }

    ValueVector V(N);

    std::iota(V.begin(), V.end(), 1);

    PairMatrix G(N + 1);

    solve(V, G, dinic);

    ValueMatrix dist(N + 1, ValueVector(N + 1, std::numeric_limits<valueType>::max()));

    for (valueType i = 1; i <= N; ++i) {
        dfs(i, 0, G, dist[i]);

        dist[i][i] = 0;
    }

    {
        valueType sum = 0;

        for (valueType i = 1; i <= N; ++i)
            for (valueType j = 1; j < i; ++j)
                sum += dist[i][j];

        std::cerr << sum << std::endl;
    }

    valueType Q;

    std::cin >> Q;

    for (valueType q = 0; q < Q; ++q) {
        valueType u, v;

        std::cin >> u >> v;

        // ++u;
        // ++v;

        std::cout << dist[u][v] << '\n';
    }

    std::cout << std::flush;

    return 0;
}

[CQOI2016] 不同的最小割

建出最小割树后将所有点对的最小割去重即可。

Code
#include <bits/stdc++.h>

typedef long long valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<ValueVector> ValueMatrix;
typedef std::pair<valueType, valueType> ValuePair;
typedef std::vector<ValuePair> PairVector;
typedef std::vector<PairVector> PairMatrix;

class Dinic {
private:
    struct Edge {
    public:
        typedef std::list<Edge> container;
        typedef container::iterator iterator;

        valueType to;
        valueType cap;
        valueType flow;
        iterator pair;

        Edge() : to(-1), cap(-1), flow(-1), pair(){};

        Edge(valueType to, valueType cap, iterator pair = iterator()) : to(to), cap(cap), flow(0), pair(pair){};
    };

    typedef std::vector<Edge::container> Graph;
    typedef std::vector<Edge::iterator> IterVector;

    valueType N;
    Graph G;
    ValueVector depth;
    IterVector start;
    bool Initialized;

public:
    explicit Dinic(valueType N) : N(N), G(N + 1), depth(N + 1, 0), start(N + 1), Initialized(false){};

    void addEdge(valueType x, valueType y, valueType cap) {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: addEdge after init");

        G[x].emplace_back(y, cap);
        G[y].emplace_back(x, cap);
        G[x].back().pair = std::prev(G[y].end());
        G[y].back().pair = std::prev(G[x].end());
    }

    void init() {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: init twice");

        Initialized = true;

        std::fill(depth.begin(), depth.end(), 0);

        for (valueType i = 1; i <= N; ++i)
            start[i] = G[i].begin();
    }

    void reset() {
        for (valueType i = 1; i <= N; ++i)
            for (auto &iter : G[i])
                iter.flow = 0;

        std::fill(depth.begin(), depth.end(), 0);

        Initialized = false;
    }

    valueType maxFlow(valueType S, valueType T) {
        if (__builtin_expect(!Initialized, false))
            throw std::runtime_error("Dinic: maxFlow before init");

        valueType result = 0;

        while (bfs(S, T)) {
            IterVector begin = start;

            result += dfs(S, T, std::numeric_limits<valueType>::max(), begin);
        }

        return result;
    }

    bool reachable(valueType n) const {
        return depth[n] > 0;
    }

private:
    bool bfs(valueType S, valueType T) {
        std::fill(depth.begin(), depth.end(), 0);

        std::queue<valueType> Q;

        Q.push(S);
        depth[S] = 1;

        while (!Q.empty()) {
            valueType const u = Q.front();

            Q.pop();

            for (auto const &e : G[u]) {
                if ((e.cap > e.flow) && (!depth[e.to])) {
                    depth[e.to] = depth[u] + 1;
                    Q.push(e.to);
                }
            }
        }

        return depth[T] > 0;
    }

    valueType dfs(valueType u, valueType T, valueType flow, IterVector &Begin) {
        if (u == T || flow == 0)
            return flow;

        valueType result = 0;

        for (auto &e = Begin[u]; e != G[u].end(); ++e) {
            if (e->cap > e->flow && depth[e->to] == depth[u] + 1) {
                valueType const f = dfs(e->to, T, std::min(flow - result, e->cap - e->flow), Begin);

                e->flow += f;
                e->pair->flow -= f;

                result += f;

                if (result == flow)
                    return flow;
            }
        }

        return result;
    }
};

void solve(ValueVector const &V, PairMatrix &G, Dinic &dinic) {
    if (V.size() < 2)
        return;

    valueType const S = V.front(), T = V.back();

    dinic.reset();

    dinic.init();

    valueType const weight = dinic.maxFlow(S, T);

    G[S].emplace_back(T, weight);
    G[T].emplace_back(S, weight);

    ValueVector A, B;

    for (auto const &iter : V) {
        if (dinic.reachable(iter))
            A.emplace_back(iter);
        else
            B.emplace_back(iter);
    }

    solve(A, G, dinic);
    solve(B, G, dinic);
}

void dfs(valueType x, valueType from, PairMatrix const &G, ValueVector &dist) {
    for (auto const &[to, weight] : G[x]) {
        if (to == from)
            continue;

        dist[to] = std::min(dist[x], weight);

        dfs(to, x, G, dist);
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    valueType N, M;

    std::cin >> N >> M;

    Dinic dinic(N);

    for (valueType i = 0; i < M; ++i) {
        valueType u, v, w;

        std::cin >> u >> v >> w;

        dinic.addEdge(u, v, w);
    }

    ValueVector V(N);

    std::iota(V.begin(), V.end(), 1);

    PairMatrix G(N + 1);

    solve(V, G, dinic);

    ValueMatrix dist(N + 1, ValueVector(N + 1, std::numeric_limits<valueType>::max()));

    for (valueType i = 1; i <= N; ++i) {
        dfs(i, 0, G, dist[i]);

        dist[i][i] = 0;
    }

    ValueVector pool;

    pool.reserve(N * (N - 1) / 2);

    for (valueType i = 1; i <= N; ++i)
        for (valueType j = 1; j < i; ++j)
            pool.emplace_back(dist[i][j]);

    std::sort(pool.begin(), pool.end());

    pool.erase(std::unique(pool.begin(), pool.end()), pool.end());

    std::cout << pool.size() << std::endl;

    return 0;
}

[ZJOI2011] 最小割

注意在两组测试数据之间需要输出一行空行。

Code
#include <bits/stdc++.h>

typedef long long valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<ValueVector> ValueMatrix;
typedef std::pair<valueType, valueType> ValuePair;
typedef std::vector<ValuePair> PairVector;
typedef std::vector<PairVector> PairMatrix;

class Dinic {
private:
    struct Edge {
    public:
        typedef std::list<Edge> container;
        typedef container::iterator iterator;

        valueType to;
        valueType cap;
        valueType flow;
        iterator pair;

        Edge() : to(-1), cap(-1), flow(-1), pair(){};

        Edge(valueType to, valueType cap, iterator pair = iterator()) : to(to), cap(cap), flow(0), pair(pair){};
    };

    typedef std::vector<Edge::container> Graph;
    typedef std::vector<Edge::iterator> IterVector;

    valueType N;
    Graph G;
    ValueVector depth;
    IterVector start;
    bool Initialized;

public:
    explicit Dinic(valueType N) : N(N), G(N + 1), depth(N + 1, 0), start(N + 1), Initialized(false){};

    void addEdge(valueType x, valueType y, valueType cap) {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: addEdge after init");

        G[x].emplace_back(y, cap);
        G[y].emplace_back(x, cap);
        G[x].back().pair = std::prev(G[y].end());
        G[y].back().pair = std::prev(G[x].end());
    }

    void init() {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: init twice");

        Initialized = true;

        std::fill(depth.begin(), depth.end(), 0);

        for (valueType i = 1; i <= N; ++i)
            start[i] = G[i].begin();
    }

    void reset() {
        for (valueType i = 1; i <= N; ++i)
            for (auto &iter : G[i])
                iter.flow = 0;

        std::fill(depth.begin(), depth.end(), 0);

        Initialized = false;
    }

    valueType maxFlow(valueType S, valueType T) {
        if (__builtin_expect(!Initialized, false))
            throw std::runtime_error("Dinic: maxFlow before init");

        valueType result = 0;

        while (bfs(S, T)) {
            IterVector begin = start;

            result += dfs(S, T, std::numeric_limits<valueType>::max(), begin);
        }

        return result;
    }

    bool reachable(valueType n) const {
        return depth[n] > 0;
    }

private:
    bool bfs(valueType S, valueType T) {
        std::fill(depth.begin(), depth.end(), 0);

        std::queue<valueType> Q;

        Q.push(S);
        depth[S] = 1;

        while (!Q.empty()) {
            valueType const u = Q.front();

            Q.pop();

            for (auto const &e : G[u]) {
                if ((e.cap > e.flow) && (!depth[e.to])) {
                    depth[e.to] = depth[u] + 1;
                    Q.push(e.to);
                }
            }
        }

        return depth[T] > 0;
    }

    valueType dfs(valueType u, valueType T, valueType flow, IterVector &Begin) {
        if (u == T || flow == 0)
            return flow;

        valueType result = 0;

        for (auto &e = Begin[u]; e != G[u].end(); ++e) {
            if (e->cap > e->flow && depth[e->to] == depth[u] + 1) {
                valueType const f = dfs(e->to, T, std::min(flow - result, e->cap - e->flow), Begin);

                e->flow += f;
                // e->pair->flow -= f;

                result += f;

                if (result == flow)
                    return flow;
            }
        }

        return result;
    }
};

void solve(ValueVector const &V, PairMatrix &G, Dinic &dinic) {
    if (V.size() < 2)
        return;

    valueType const S = V.front(), T = V.back();

    dinic.reset();

    dinic.init();

    valueType const weight = dinic.maxFlow(S, T);

    G[S].emplace_back(T, weight);
    G[T].emplace_back(S, weight);

    ValueVector A, B;

    for (auto const &iter : V) {
        if (dinic.reachable(iter))
            A.emplace_back(iter);
        else
            B.emplace_back(iter);
    }

    solve(A, G, dinic);
    solve(B, G, dinic);
}

void dfs(valueType x, valueType from, PairMatrix const &G, ValueVector &dist) {
    for (auto const &[to, weight] : G[x]) {
        if (to == from)
            continue;

        dist[to] = std::min(dist[x], weight);

        dfs(to, x, G, dist);
    }
}

void solve() {
    valueType N, M;

    std::cin >> N >> M;

    Dinic dinic(N);

    for (valueType i = 0; i < M; ++i) {
        valueType u, v, w;

        std::cin >> u >> v >> w;

        dinic.addEdge(u, v, w);
    }

    ValueVector V(N);

    std::iota(V.begin(), V.end(), 1);

    PairMatrix G(N + 1);

    solve(V, G, dinic);

    ValueMatrix dist(N + 1, ValueVector(N + 1, std::numeric_limits<valueType>::max()));

    for (valueType i = 1; i <= N; ++i) {
        dfs(i, 0, G, dist[i]);

        dist[i][i] = 0;
    }

    ValueVector pool;

    pool.reserve(N * (N - 1) / 2);

    for (valueType i = 1; i <= N; ++i)
        for (valueType j = 1; j < i; ++j)
            pool.emplace_back(dist[i][j]);

    std::sort(pool.begin(), pool.end());

    valueType Q;

    std::cin >> Q;

    for (valueType q = 0 ; q < Q; ++q) {
        valueType x;

        std::cin >> x;

        std::cout << std::distance(pool.begin(), std::upper_bound(pool.begin(), pool.end(), x)) << '\n';
    }

    std::cout << std::endl;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    valueType T;

    std::cin >> T;

    for (valueType i = 0; i < T; ++i)
        solve();

    std::cout << std::flush;

    return 0;
}

[CERC2015] Juice Junctions

因为最大流的值等于最小割的值,因此建最小割树求出所有点对间的最小割即可。

Code
#include <bits/stdc++.h>

typedef long long valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<ValueVector> ValueMatrix;
typedef std::pair<valueType, valueType> ValuePair;
typedef std::vector<ValuePair> PairVector;
typedef std::vector<PairVector> PairMatrix;

class Dinic {
private:
    struct Edge {
    public:
        typedef std::list<Edge> container;
        typedef container::iterator iterator;

        valueType to;
        valueType cap;
        valueType flow;
        iterator pair;

        Edge() : to(-1), cap(-1), flow(-1), pair(){};

        Edge(valueType to, valueType cap, iterator pair = iterator()) : to(to), cap(cap), flow(0), pair(pair){};
    };

    typedef std::vector<Edge::container> Graph;
    typedef std::vector<Edge::iterator> IterVector;

    valueType N;
    Graph G;
    ValueVector depth;
    IterVector start;
    bool Initialized;

public:
    explicit Dinic(valueType N) : N(N), G(N + 1), depth(N + 1, 0), start(N + 1), Initialized(false){};

    void addEdge(valueType x, valueType y, valueType cap) {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: addEdge after init");

        G[x].emplace_back(y, cap);
        G[y].emplace_back(x, cap);
        G[x].back().pair = std::prev(G[y].end());
        G[y].back().pair = std::prev(G[x].end());
    }

    void init() {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: init twice");

        Initialized = true;

        std::fill(depth.begin(), depth.end(), 0);

        for (valueType i = 1; i <= N; ++i)
            start[i] = G[i].begin();
    }

    void reset() {
        for (valueType i = 1; i <= N; ++i)
            for (auto &iter : G[i])
                iter.flow = 0;

        std::fill(depth.begin(), depth.end(), 0);

        Initialized = false;
    }

    valueType maxFlow(valueType S, valueType T) {
        if (__builtin_expect(!Initialized, false))
            throw std::runtime_error("Dinic: maxFlow before init");

        valueType result = 0;

        while (bfs(S, T)) {
            IterVector begin = start;

            result += dfs(S, T, std::numeric_limits<valueType>::max(), begin);
        }

        return result;
    }

    bool reachable(valueType n) const {
        return depth[n] > 0;
    }

private:
    bool bfs(valueType S, valueType T) {
        std::fill(depth.begin(), depth.end(), 0);

        std::queue<valueType> Q;

        Q.push(S);
        depth[S] = 1;

        while (!Q.empty()) {
            valueType const u = Q.front();

            Q.pop();

            for (auto const &e : G[u]) {
                if ((e.cap > e.flow) && (!depth[e.to])) {
                    depth[e.to] = depth[u] + 1;
                    Q.push(e.to);
                }
            }
        }

        return depth[T] > 0;
    }

    valueType dfs(valueType u, valueType T, valueType flow, IterVector &Begin) {
        if (u == T || flow == 0)
            return flow;

        valueType result = 0;

        for (auto &e = Begin[u]; e != G[u].end(); ++e) {
            if (e->cap > e->flow && depth[e->to] == depth[u] + 1) {
                valueType const f = dfs(e->to, T, std::min(flow - result, e->cap - e->flow), Begin);

                e->flow += f;
                e->pair->flow -= f;

                result += f;

                if (result == flow)
                    return flow;
            }
        }

        return result;
    }
};

void solve(ValueVector const &V, PairMatrix &G, Dinic &dinic) {
    if (V.size() < 2)
        return;

    valueType const S = V.front(), T = V.back();

    dinic.reset();

    dinic.init();

    valueType const weight = dinic.maxFlow(S, T);

    G[S].emplace_back(T, weight);
    G[T].emplace_back(S, weight);

    ValueVector A, B;

    for (auto const &iter : V) {
        if (dinic.reachable(iter))
            A.emplace_back(iter);
        else
            B.emplace_back(iter);
    }

    solve(A, G, dinic);
    solve(B, G, dinic);
}

void dfs(valueType x, valueType from, PairMatrix const &G, ValueVector &dist) {
    for (auto const &[to, weight] : G[x]) {
        if (to == from)
            continue;

        dist[to] = std::min(dist[x], weight);

        dfs(to, x, G, dist);
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    valueType N, M;

    std::cin >> N >> M;

    Dinic dinic(N);

    for (valueType i = 0; i < M; ++i) {
        valueType u, v;

        std::cin >> u >> v;

        dinic.addEdge(u, v, 1);
    }

    ValueVector V(N);

    std::iota(V.begin(), V.end(), 1);

    PairMatrix G(N + 1);

    solve(V, G, dinic);

    ValueMatrix dist(N + 1, ValueVector(N + 1, std::numeric_limits<valueType>::max()));

    for (valueType i = 1; i <= N; ++i) {
        dfs(i, 0, G, dist[i]);

        dist[i][i] = 0;
    }

    ValueVector pool;

    pool.reserve(N * (N - 1) / 2);

    for (valueType i = 1; i <= N; ++i)
        for (valueType j = 1; j < i; ++j)
            pool.emplace_back(dist[i][j]);

    std::cout << std::accumulate(pool.begin(), pool.end(), (valueType) 0) << std::endl;

    return 0;
}

UVA11594 All Pairs Maximum Flow

注意 \(\tt{UVA}\) 要求输出内容中不含有多余的空格和空行。

Code
#include <bits/stdc++.h>

typedef long long valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<ValueVector> ValueMatrix;
typedef std::pair<valueType, valueType> ValuePair;
typedef std::vector<ValuePair> PairVector;
typedef std::vector<PairVector> PairMatrix;

class Dinic {
private:
    struct Edge {
    public:
        typedef std::list<Edge> container;
        typedef container::iterator iterator;

        valueType to;
        valueType cap;
        valueType flow;
        iterator pair;

        Edge() : to(-1), cap(-1), flow(-1), pair(){};

        Edge(valueType to, valueType cap, iterator pair = iterator()) : to(to), cap(cap), flow(0), pair(pair){};
    };

    typedef std::vector<Edge::container> Graph;
    typedef std::vector<Edge::iterator> IterVector;

    valueType N;
    Graph G;
    ValueVector depth;
    IterVector start;
    bool Initialized;

public:
    explicit Dinic(valueType N) : N(N), G(N + 1), depth(N + 1, 0), start(N + 1), Initialized(false){};

    void addEdge(valueType x, valueType y, valueType cap) {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: addEdge after init");

        G[x].emplace_back(y, cap);
        G[y].emplace_back(x, cap);
        G[x].back().pair = std::prev(G[y].end());
        G[y].back().pair = std::prev(G[x].end());
    }

    void init() {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: init twice");

        Initialized = true;

        std::fill(depth.begin(), depth.end(), 0);

        for (valueType i = 1; i <= N; ++i)
            start[i] = G[i].begin();
    }

    void reset() {
        for (valueType i = 1; i <= N; ++i)
            for (auto &iter : G[i])
                iter.flow = 0;

        std::fill(depth.begin(), depth.end(), 0);

        Initialized = false;
    }

    valueType maxFlow(valueType S, valueType T) {
        if (__builtin_expect(!Initialized, false))
            throw std::runtime_error("Dinic: maxFlow before init");

        valueType result = 0;

        while (bfs(S, T)) {
            IterVector begin = start;

            result += dfs(S, T, std::numeric_limits<valueType>::max(), begin);
        }

        return result;
    }

    bool reachable(valueType n) const {
        return depth[n] > 0;
    }

private:
    bool bfs(valueType S, valueType T) {
        std::fill(depth.begin(), depth.end(), 0);

        std::queue<valueType> Q;

        Q.push(S);
        depth[S] = 1;

        while (!Q.empty()) {
            valueType const u = Q.front();

            Q.pop();

            for (auto const &e : G[u]) {
                if ((e.cap > e.flow) && (!depth[e.to])) {
                    depth[e.to] = depth[u] + 1;
                    Q.push(e.to);
                }
            }
        }

        return depth[T] > 0;
    }

    valueType dfs(valueType u, valueType T, valueType flow, IterVector &Begin) {
        if (u == T || flow == 0)
            return flow;

        valueType result = 0;

        for (auto &e = Begin[u]; e != G[u].end(); ++e) {
            if (e->cap > e->flow && depth[e->to] == depth[u] + 1) {
                valueType const f = dfs(e->to, T, std::min(flow - result, e->cap - e->flow), Begin);

                e->flow += f;
                e->pair->flow -= f;

                result += f;

                if (result == flow)
                    return flow;
            }
        }

        return result;
    }
};

void solve(ValueVector const &V, PairMatrix &G, Dinic &dinic) {
    if (V.size() < 2)
        return;

    valueType const S = V.front(), T = V.back();

    dinic.reset();

    dinic.init();

    valueType const weight = dinic.maxFlow(S, T);

    G[S].emplace_back(T, weight);
    G[T].emplace_back(S, weight);

    ValueVector A, B;

    for (auto const &iter : V) {
        if (dinic.reachable(iter))
            A.emplace_back(iter);
        else
            B.emplace_back(iter);
    }

    solve(A, G, dinic);
    solve(B, G, dinic);
}

void dfs(valueType x, valueType from, PairMatrix const &G, ValueVector &dist) {
    for (auto const &[to, weight] : G[x]) {
        if (to == from)
            continue;

        dist[to] = std::min(dist[x], weight);

        dfs(to, x, G, dist);
    }
}

void solve(valueType id) {
    valueType N;

    std::cin >> N;

    Dinic dinic(N);

    for (valueType i = 1; i <= N; ++i) {
        for (valueType j = 1; j <= N; ++j) {
            valueType w;

            std::cin >> w;

            if (w != 0 && i > j)
                dinic.addEdge(i, j, w);
        }
    }

    ValueVector V(N);

    std::iota(V.begin(), V.end(), 1);

    PairMatrix G(N + 1);

    solve(V, G, dinic);

    ValueMatrix dist(N + 1, ValueVector(N + 1, std::numeric_limits<valueType>::max()));

    for (valueType i = 1; i <= N; ++i) {
        dfs(i, 0, G, dist[i]);

        dist[i][i] = 0;
    }

    std::cout << "Case #" << id << ":" << std::endl;

    for (valueType i = 1; i <= N; ++i) {
        for (valueType j = 1; j <= N; ++j)
            std::cout << dist[i][j] << " \n"[j == N];
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    valueType T;

    std::cin >> T;

    for (valueType i = 1; i <= T; ++i)
        solve(i);

    std::cout << std::flush;

    return 0;
}
posted @ 2023-12-05 12:02  User-Unauthorized  阅读(17)  评论(0编辑  收藏  举报