首页 > 其他分享 >Solution Set 2023.12.4

Solution Set 2023.12.4

时间:2023-12-04 16:13:12浏览次数:35  
标签:std typedef Set const 2023.12 valueType flow Solution false

来衡实了,感觉良好。


[NOIP2023] 三值逻辑

一直以为是写假了,结果是写挂了,没有判自环的同时 \(u, v\) 输入反了。

考虑对于每个变量的每个版本均开一个节点,那么赋值关系可以用有向边表示,可以发现最终得到的一定是若干外向基环树和若干外向树组成的图。且被 \(\tt{T,F,U}\) 三种指令赋值的节点一定是外向树的根,不会引起冲突。因此只需要考虑所有的基环树即可。从基环树的环开始递归染色,若冲突则整课树的值均为 \(\tt{U}\)。

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

typedef int valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<ValueVector> ValueMatrix;
typedef std::vector<bool> bitset;
typedef std::queue<valueType> ValueQueue;
typedef std::pair<valueType, valueType> ValuePair;
typedef std::vector<ValuePair> PairVector;
typedef std::vector<PairVector> PairMatrix;

valueType N, M, S;
ValueVector color, now, degree;
PairMatrix G;
ValueMatrix revG;
bitset undefined;

bool push(valueType x) {
    bool success = true;

    undefined[x] = false;

    for (auto const &[to, w] : G[x]) {
        if (undefined[to]) {
            color[to] = color[x] * w;
            undefined[to] = false;

            if (!push(to))
                success = false;
        } else {
            if (color[to] != color[x] * w)
                success = false;
        }
    }

    return success;
}

void pushZero(valueType x) {
    color[x] = 0;

    for (auto const &[to, w] : G[x]) {
        if (color[to] != 0)
            pushZero(to);
    }
}

void solve() {
    std::cin >> N >> M;

    S = N + M;

    color.resize(S + 1, 1);
    G.resize(S + 1);
    revG.resize(S + 1);
    undefined.resize(S + 1, true);
    degree.resize(S + 1, 0);
    now.resize(N + 1);
    std::iota(now.begin(), now.end(), 0);

    valueType count = N;

    for (valueType m = 0; m < M; ++m) {
        char type;

        std::cin >> type;

        if (type == 'T') {
            valueType x;

            std::cin >> x;

            now[x] = ++count;

            undefined[now[x]] = false;

            color[now[x]] = 1;
        } else if (type == 'F') {
            valueType x;

            std::cin >> x;

            now[x] = ++count;

            undefined[now[x]] = false;

            color[now[x]] = -1;
        } else if (type == 'U') {
            valueType x;

            std::cin >> x;

            now[x] = ++count;

            undefined[now[x]] = false;

            color[now[x]] = 0;
        } else if (type == '+') {
            valueType u, v;

            std::cin >> v >> u;

            valueType const from = now[u];

            now[v] = ++count;

            G[from].emplace_back(now[v], 1);
            assert(undefined[now[v]]);
            revG[now[v]].emplace_back(from);
            ++degree[from];
        } else {
            valueType u, v;

            std::cin >> v >> u;

            valueType const from = now[u];

            now[v] = ++count;

            G[from].emplace_back(now[v], -1);
            assert(undefined[now[v]]);
            revG[now[v]].emplace_back(from);
            ++degree[from];
        }
    }

    for (valueType i = 1; i <= N; ++i) {
        G[now[i]].emplace_back(i, 1);
        assert(undefined[i]);
        revG[i].emplace_back(now[i]);
        ++degree[now[i]];
    }

    assert(count == S);

    S = count;

    bitset const undefinedCopy = undefined;

    for (valueType i = 1; i <= S; ++i) {
        if (undefinedCopy[i])
            continue;

        assert(revG[i].empty());

        undefined[i] = false;

        if (!push(i))
            std::abort();
    }

    ValueQueue Q;

    for (valueType i = 1; i <= S; ++i) {
        if (degree[i] == 0)
            Q.push(i);
    }

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

        Q.pop();

        for (auto const &iter : revG[x])
            if (--degree[iter] == 0)
                Q.push(iter);
    }

    for (valueType i = 1; i <= S; ++i) {
        if (undefined[i] && degree[i] != 0) {
            color[i] = 1;
            undefined[i] = false;

            if (!push(i))
                pushZero(i);
        }
    }

    for (valueType i = 1; i <= S; ++i)
        assert(!undefined[i]);

    valueType ans = 0;

    for (valueType i = 1; i <= N; ++i) {
        assert(color[i] == color[now[i]]);
        
        if (color[i] == 0)
            ++ans;
    }

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

void clear() {
    N = M = S = 0;
    color.clear();
    now.clear();
    degree.clear();
    G.clear();
    undefined.clear();
    revG.clear();
}

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

// #ifndef LOCAL_STDIO
//     freopen("tribool.in", "r", stdin);
//     freopen("tribool.out", "w", stdout);
// #endif

    valueType ID, T;

    std::cin >> ID >> T;

    for (valueType testcase = 0; testcase < T; ++testcase) {
        clear();
        
        solve();
    }

    return 0;
}

[NOIP2023] 双序列拓展

首先考虑一个 \(\mathcal{O}(nm)\) 的 \(\tt{DP}\),设 \(f_{i, j}\) 表示是否存在方案使得 \(X_i\) 与 \(Y_j\) 配对。那么有转移:

\[f_{i, j} = f_{i - 1, j} \text{ OR } f_{i, j - 1} \text{ OR } f_{i - 1, j - 1} \]

考虑上述的过程在干什么,设 \(X_1 < Y_1\),那么我们可以构造出一个 \(n \times m\) 的网格 \(A\),满足 \(A_{i, j} = \left[X_i < Y_j\right]\)。

那么 \(f_{i, j}\) 实质上表示的就是从 \(\left(1, 1\right)\) 只向下,右或右下移动是否可以到达 \(\left(i, j\right)\)。

考虑特殊性质下的方格图,设 \(X_{\min}\) 表示 \(X\) 的最小值,\(X_{\max}\) 表示 \(X\) 的最大值,\(Y_{\min}\) 表示 \(Y\) 的最小值,\(Y_{\max}\) 表示 \(Y\) 的最大值。

那么如果 \(X_{\min} \ge Y_{\min}\) 或者 \(X_{\max} \ge Y_{\max}\),那么一定无解。

所以有 \(X_{\min} < Y_{\min}, X_{\max} < Y_{\max}\)。

转化到网格图上,可以发现图的最后一行和最后一列的值均为 \(1\),所以只要可以从 \(\left(1, 1\right)\) 到达最后一行或最后一列的任意一个格子均可以到达 \(\left(n, m\right)\)。发现此时最后一行或最后一列可以视为一个边界。考虑前 \(n - 1\) 行和 \(m - 1\) 列,发现我们可以继续寻找出两个序列的极值并继续收缩边界,直到收缩到第 \(1\) 行或第 \(1\) 列或在中途发现无解。

在没有特殊限制的情况下可以通过序列极值构成的十字架将网格分为四部分,对于左上和右下部分分别处理即可。

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

typedef int valueType;
typedef std::vector<valueType> ValueVector;
typedef std::pair<valueType, valueType> ValuePair;
typedef std::vector<ValuePair> PairVector;

namespace MAIN {
    PairVector PreMaxA, PreMinA, SufMaxA, SufMinA;
    PairVector PreMaxB, PreMinB, SufMaxB, SufMinB;

    bool checkUp(valueType X, valueType Y, valueType N, valueType M) {
        if (X == 1 || Y == 1)
            return true;

        auto const &[MinA, MinA_Pos] = PreMinA[X - 1];
        auto const &[MaxA, MaxA_Pos] = PreMaxA[X - 1];
        auto const &[MinB, MinB_Pos] = PreMinB[Y - 1];
        auto const &[MaxB, MaxB_Pos] = PreMaxB[Y - 1];

        if (MinA < MinB)
            return checkUp(MinA_Pos, Y, N, M);

        if (MaxB > MaxA)
            return checkUp(X, MaxB_Pos, N, M);

        return false;
    }

    bool checkDown(valueType X, valueType Y, valueType N, valueType M) {
        if (X == N || Y == M)
            return true;

        auto const &[MinA, MinA_Pos] = SufMinA[X + 1];
        auto const &[MaxA, MaxA_Pos] = SufMaxA[X + 1];
        auto const &[MinB, MinB_Pos] = SufMinB[Y + 1];
        auto const &[MaxB, MaxB_Pos] = SufMaxB[Y + 1];

        if (MinA < MinB)
            return checkDown(MinA_Pos, Y, N, M);

        if (MaxB > MaxA)
            return checkDown(X, MaxB_Pos, N, M);

        return false;
    }

    bool solve(valueType N, valueType M, ValueVector const &A, ValueVector const &B) {
        PreMaxA.clear();
        PreMinA.clear();
        SufMaxA.clear();
        SufMinA.clear();
        PreMaxB.clear();
        PreMinB.clear();
        SufMaxB.clear();
        SufMinB.clear();

        PreMaxA.resize(N + 1);
        PreMinA.resize(N + 1);
        SufMaxA.resize(N + 1);
        SufMinA.resize(N + 1);
        PreMaxB.resize(M + 1);
        PreMinB.resize(M + 1);
        SufMaxB.resize(M + 1);
        SufMinB.resize(M + 1);

        if (A[1] >= B[1])
            return false;

        PreMaxA[1] = ValuePair(A[1], 1);
        PreMinA[1] = ValuePair(A[1], 1);

        for (valueType i = 2; i <= N; ++i) {
            PreMaxA[i] = std::max(PreMaxA[i - 1], ValuePair(A[i], i));
            PreMinA[i] = std::min(PreMinA[i - 1], ValuePair(A[i], i));
        }

        SufMaxA[N] = ValuePair(A[N], N);
        SufMinA[N] = ValuePair(A[N], N);

        for (valueType i = N - 1; i >= 1; --i) {
            SufMaxA[i] = std::max(SufMaxA[i + 1], ValuePair(A[i], i));
            SufMinA[i] = std::min(SufMinA[i + 1], ValuePair(A[i], i));
        }

        PreMaxB[1] = ValuePair(B[1], 1);
        PreMinB[1] = ValuePair(B[1], 1);

        for (valueType i = 2; i <= M; ++i) {
            PreMaxB[i] = std::max(PreMaxB[i - 1], ValuePair(B[i], i));
            PreMinB[i] = std::min(PreMinB[i - 1], ValuePair(B[i], i));
        }

        SufMaxB[M] = ValuePair(B[M], M);
        SufMinB[M] = ValuePair(B[M], M);

        for (valueType i = M - 1; i >= 1; --i) {
            SufMaxB[i] = std::max(SufMaxB[i + 1], ValuePair(B[i], i));
            SufMinB[i] = std::min(SufMinB[i + 1], ValuePair(B[i], i));
        }

        auto const &[MinA, MinA_Pos] = PreMinA[N];
        auto const &[MaxA, MaxA_Pos] = PreMaxA[N];
        auto const &[MinB, MinB_Pos] = PreMinB[M];
        auto const &[MaxB, MaxB_Pos] = PreMaxB[M];

        if (MinA >= MinB || MaxA >= MaxB)
            return false;

        return checkUp(MinA_Pos, MaxB_Pos, N, M) && checkDown(MinA_Pos, MaxB_Pos, N, M);
    }
}// namespace MAIN

using MAIN::solve;

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

    // #ifndef LOCAL_STDIO
    //     freopen("expand.in", "r", stdin);
    //     freopen("expand.out", "w", stdout);
    // #endif

    valueType ID, N, M, Q;

    std::cin >> ID >> N >> M >> Q;

    ValueVector A(N + 1), B(M + 1);

    for (valueType i = 1; i <= N; ++i)
        std::cin >> A[i];

    for (valueType i = 1; i <= M; ++i)
        std::cin >> B[i];

    std::cout << ((solve(N, M, A, B) || solve(M, N, B, A)) ? 1 : 0);

    for (valueType query = 0; query < Q; ++query) {
        valueType KA, KB;

 

因此对于点
,向 和点 连一条容量为

的边即可。
Code

    [NOIP2023] 三值逻辑
    [NOIP2023] 双序列拓展
    [SDOI2016] 数字配对
    [HNOI2013] 切糕


__EOF__
本文作者: User-Unauthorized
本文链接: https://www.cnblogs.com/User-Unauthorized/p/2023-12-4.html
关于博主: 评论和私信会在第一时间回复。或者直接私信我。
版权声明: 本博客所       std::cin >> KA >> KB;

        ValueVector TA = A, TB = B;

        for (valueType i = 0; i < KA; ++i) {
            valueType x, y;

            std::cin >> x >> y;

            TA[x] = y;
        }

        for (valueType i = 0; i < KB; ++i) {
            valueType x, y;

            std::cin >> x >> y;

            TB[x] = y;
        }

        std::cout << ((solve(N, M, TA, TB) || solve(M, N, TB, TA)) ? 1 : 0);
    }

    std::cout << std::endl;

    return 0;
}

[SDOI2016] 数字配对

对于每个数 \(i\),设 \(f_i\) 表示 \(a_i\) 的所有质因子的次数之和。那么两个数 \(i, j\) 可以配对当且仅当 \(a_i \mid a_j \land f_j = f_i + 1\) 或 \(a_j \mid a_i \land f_i = f_j + 1\)。

所以 \(f_i\) 奇偶性相同的数之间一定不可能配对,考虑将 \(f_i\) 为奇数的点作为左部点,\(f_i\) 为偶数的点作为右部点,在可以配对的数对之间连边,可以发现形成的网络为一个二分图。

那么接下来问题转化为了如何在获得的价值总和不小于 \(0\) 的前提下求出最大流。

考虑应用最大费用最大流,因为其均为剩余网络中的最长路,因此每轮增广后剩余网络中的最长路单调递减。

因此当前轮增广后的费用为负时退掉一些流使得费用为正后退出即可。

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

typedef long long valueType;
typedef std::vector<valueType> ValueVector;

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

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

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

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

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

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

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

    Edge::iterator addEdge(valueType from, valueType to, valueType cap, valueType cost) {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("MCMF: addEdge after init");

        G[from].emplace_back(to, cap, cost);
        G[to].emplace_back(from, 0, -cost);
        G[from].back().pair = std::prev(G[to].end());
        G[to].back().pair = std::prev(G[from].end());

        return std::prev(G[from].end());
    }

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

        Initialized = true;

        std::fill(dist.begin(), dist.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("MCMF: reset before init");

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

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

        Initialized = false;
    }

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

        std::pair<valueType, valueType> result(0, 0);

        while (bfs(S, T)) {
            IterVector begin = start;
            
            bitset visited(N + 1, false);

            valueType const flow = dfs(S, T, std::numeric_limits<valueType>::max(), begin, visited);
            
            if (result.second + flow * dist[T] < 0) {
                result.first += -result.second / dist[T];
                result.second += result.second / dist[T] * dist[T];

                break;
            }

            result.first += flow;
            result.second += flow * dist[T];
        }

        return result;
    }

private:
    bool bfs(valueType S, valueType T) {
        std::fill(dist.begin(), dist.end(), std::numeric_limits<valueType>::min() >> 5);

        bitset visited(N + 1, false);

        std::queue<valueType> Q;

        Q.push(S);
        dist[S] = 0;
        visited[S] = true;

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

            visited[u] = false;
            Q.pop();

            for (auto const &e : G[u]) {
                if ((e.cap > e.flow) && (dist[e.to] < dist[u] + e.cost)) {
                    dist[e.to] = dist[u] + e.cost;

                    if (!visited[e.to]) {
                        Q.push(e.to);
                        visited[e.to] = true;
                    }
                }
            }
        }

        return dist[T] != (std::numeric_limits<valueType>::min() >> 5);
    }

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

        valueType result = 0;

        visited[u] = true;

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

                if (f == 0) {
                    dist[e->to] = std::numeric_limits<valueType>::min();

                    continue;
                }

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

                result += f;

                if (result == flow) {
                    visited[u] = false;

                    return flow;
                }
            }
        }

        visited[u] = false;

        return result;
    }
};

constexpr valueType INF = std::numeric_limits<valueType>::max();

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

    valueType N;

    std::cin >> N;

    valueType const S = N + 1, T = N + 2;

    MCMF mcmf(N + 3);

    ValueVector A(N + 1), B(N + 1), C(N + 1), count(N + 1, 0);

    for (valueType i = 1; i <= N; ++i)
        std::cin >> A[i];

    for (valueType i = 1; i <= N; ++i)
        std::cin >> B[i];

    for (valueType i = 1; i <= N; ++i)
        std::cin >> C[i];

    for (valueType i = 1; i <= N; ++i) {
        valueType x = A[i];

        for (valueType j = 2; j * j <= x; ++j) {
            while (x % j == 0) {
                x /= j;

                ++count[i];
            }
        }

        if (x > 1)
            ++count[i];
    }

    for (valueType i = 1; i <= N; ++i) {
        if ((count[i] & 1) == 1)
            mcmf.addEdge(S, i, B[i], 0);
        else
            mcmf.addEdge(i, T, B[i], 0);
    }

    for (valueType i = 1; i <= N; ++i) {
        if ((count[i] & 1) == 0)
            continue;

        for (valueType j = 1; j <= N; ++j)
            if ((A[i] % A[j] == 0 && count[i] == count[j] + 1) || (A[j] % A[i] == 0 && count[j] == count[i] + 1))
                mcmf.addEdge(i, j, INF, C[i] * C[j]);
    }

    mcmf.init();

    auto const ans = mcmf.maxFlow(S, T);

    std::cout << ans.first << std::endl;

    return 0;
}

[HNOI2013] 切糕

可以发现切面会把点分为两个集合,故考虑最小割。

发现可以从点 \(\left(x, y, z\right)\) 向 \(\left(x, y, z + 1\right)\) 连边,流量为 \(v\left(x, y, z\right)\)。其中 \(\left(x, y, 0\right) = S, v\left(x, y, 0\right) = \infty, \left(x, y, R + 1\right) = T\)

那么可以发现 \(S\) 集合意味着切面及以下的点的集合,\(T\) 集合意味着切面以上的点的集合,考虑如何处理相邻切面距离不能超过 \(D\) 的限制。

发现对于相邻的竖柱 \(a, b\),设 \(\left(a, x\right)\) 表示竖柱 \(a\) 上的第 \(x\) 层对应的节点。那么限制可以表示为

\[\forall (a, x) \in S, (b, x - D) \in S \]

因此对于点 \(\left(x, y, z\right)\),向 \(\left(x \pm 1, y, z - D\right)\) 和点 \(\left(x, y \pm 1, z - D\right)\) 连一条容量为 \(\infty\) 的边即可。

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

typedef long long valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<ValueVector> ValueMatrix;
typedef std::vector<ValueMatrix> ValueCube;

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 from, valueType to, valueType cap) {
        if (__builtin_expect(Initialized, false))
            throw std::runtime_error("Dinic: addEdge after init");

        G[from].emplace_back(to, cap);
        G[to].emplace_back(from, 0);
        G[from].back().pair = std::prev(G[to].end());
        G[to].back().pair = std::prev(G[from].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() {
        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])
                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;
    }

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;
    }
};

constexpr valueType INF = std::numeric_limits<valueType>::max();

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

    valueType P, Q, R, D;

    std::cin >> P >> Q >> R >> D;

    valueType size = 0;

    valueType const S = ++size, T = ++size;

    ValueCube ID(P + 1, ValueMatrix(Q + 1, ValueVector(R + 2, 0))), W(P + 1, ValueMatrix(Q + 1, ValueVector(R + 1, INF)));

    for (valueType i = 1; i <= P; ++i) {
        for (valueType j = 1; j <= Q; ++j) {
            for (valueType k = 1; k <= R; ++k)
                ID[i][j][k] = ++size;

            ID[i][j][0] = S;
            ID[i][j][R + 1] = T;
        }
    }

    for (valueType k = 1; k <= R; ++k)
        for (valueType i = 1; i <= P; ++i)
            for (valueType j = 1; j <= Q; ++j)
                std::cin >> W[i][j][k];

    Dinic dinic(size);

    for (valueType i = 1; i <= P; ++i)
        for (valueType j = 1; j <= Q; ++j)
            for (valueType k = 0; k <= R; ++k)
                dinic.addEdge(ID[i][j][k], ID[i][j][k + 1], W[i][j][k]);

    for (valueType i = 1; i <= P; ++i) {
        for (valueType j = 1; j <= Q; ++j) {
            for (valueType k = D; k <= R; ++k) {
                if (i > 1)
                    dinic.addEdge(ID[i][j][k], ID[i - 1][j][k - D], INF);
                
                if (i < P)
                    dinic.addEdge(ID[i][j][k], ID[i + 1][j][k - D], INF);

                if (j > 1)
                    dinic.addEdge(ID[i][j][k], ID[i][j - 1][k - D], INF);

                if (j < Q)
                    dinic.addEdge(ID[i][j][k], ID[i][j + 1][k - D], INF);
            }
        }
    }

    dinic.init();

    std::cout << dinic.maxFlow(S, T) << std::endl;

    return 0;
}

标签:std,typedef,Set,const,2023.12,valueType,flow,Solution,false
From: https://www.cnblogs.com/User-Unauthorized/p/2023-12-4.html

相关文章

  • 手写类似于BetterScroll样式的左右联动菜单 uni-app+vue3+ts (使用了script setup语法
     注意:在模拟器用鼠标滚动是不会切换光标的,因为使用的是触摸滑动。【自定义类型贴在最后了】script部分如下:import{onMounted}from'vue'importtype{orderDetail}from'@/types/category'importtype{mainArr}from'@/types/main-arr'import{nextTick,ref}......
  • python 属性装饰器和对应的setter方法,属性的封装和安全性控制
    当我们在类中定义属性时,通常希望能够对属性的读取和写入进行控制,以确保数据的完整性和安全性。属性装饰器和对应的setter方法提供了一种实现属性封装和安全性控制的方法。属性装饰器是Python的一种语法特性,用于修饰类的方法,使其表现为一个属性而不是一个普通的方法。通过使用属性......
  • 关于函数宏offset_of 和 container_of的学习
    #defineoffset_of(type,member)((unsignedint)&((type*)0)->member)#definecontainer_of(ptr,type,member)((type*)((char*)(ptr)-offset_of(type,member)))offset_of(type,member)用途:用于获取获取结构体某一个成员在该结构体中的位置参数1:type,表示......
  • 1.Java集合(List、Set、Queue)
    1.集合概述Java集合也被称为容器。主要由两个接口组成,一个是Collection接口,主要存放单一元素;一个是Map接口,主要存放键值对。Collection下面还有三个子接口,分别是List、Set、Queue。Java框架如下图所示:1.1List、Set、Queue、Map简介List(对付顺序的好帮手):存储的元素有序、......
  • 最新Unity DOTS教程之BlobAsset核心机制分析
    最近DOTS发布了正式的版本,我们来分享一下DOTS里面BlobAsset机制,方便大家上手学习掌握UnityDOTS开发。BlobAsset 概叙DOTS提供了BlobAsset机制来把数据生成高效的二进制数据。BlobAsset的数据是不可变的。BlobAsset只支持非托管类型数据。支持Burst编译器编译出来的类型。同......
  • 2023.12.3——每日总结
    学习所花时间(包括上课):9h代码量(行):0行博客量(篇):1篇今天,上午学习,下午学习;我了解到的知识点:1.jfinal明日计划:学习......
  • 你真的了解HashSet 和HashMap的区别、优缺点、使用场景吗?
     HashSet和HashMap是Java集合框架中的两个常用类,它们都用于存储和管理数据,但在使用方式、功能和性能上有很大的区别。HashSet和HashMap的区别区别一:用途不同HashSet: HashSet是一个基于哈希表的集合,用于存储不重复的元素,它不存储键值对。它实际上是基于HashMap......
  • 2023.12.02 日记
    今天abc一定是有史以来打得最好的一次。排名居然高于CHD。虽然王教授和赖爷没打。我在48min写完了A~F题。然后50min想不出G。最终的排名是142。可惜D题没有认真看数据范围导致了一次罚时,不然排名会更高。当时看到G题感觉很惊悚,我很难很快地消去长度这一个无穷项......
  • 2023.12.2——每日总结
    学习所花时间(包括上课):9h代码量(行):0行博客量(篇):1篇今天,上午学习,下午学习;我了解到的知识点:1.jfinal明日计划:学习......
  • setTimeout 函数在前端延迟搜索实现中的作用
    看这段代码:SmartFilterBar.prototype._regularTriggerSearch=function(iDelay){ if(this.getSuppressSelection()){ return; } this._clearDelayedSearch(); this._iDelayedSearchId=setTimeout(function(){ varaPromises=this._getVisibleControlsL......