• XVI Open Cup named after E.V. Pankratiev. GP of Eurasia


    C.Inequalities

    给你若干二元不等式,求一组合法解

    差分约束系统,使用最长路求解,需要用spfa看图里是否存在正权环,如果存在就无解

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i, j, k) for (int i = int(j); i <= int(k); ++ i)
    const int N = 1e5 + 7;
    typedef pair<int, int> P;
    const int inf = 2e9;
    int n, k, d[N], maxv[N], cnt[N], inq[N], q[N];
    inline int readint() {
        char c = getchar();
        while (c == '
    ' || c == ' ') c = getchar();
        int op = 1, x = 0;
        if (c == '-') op = -1, c = getchar();
        while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * op;
    }
    int ehead[N], tot = 0;
    struct  edge {
        int v, cost, next;
    }e[N << 2];
    int main() {
        scanf("%d%d", &n, &k);
        rep(i, 0, k) d[i] = -inf, maxv[i] = inf;
        bool ok = 1;
        auto add = [&](int u, int v, int w) {
            ++ tot;
            e[tot].next = ehead[u];
            e[tot].v = v;
            e[tot].cost = w;
            ehead[u] = tot;
        };
        rep(i, 1, n) {
            int op, t1, x1, t2, x2;
            op = readint(); t1 = readint(); x1 = readint(); t2 = readint(); x2 = readint();
            if (t1 == 0 && t2 == 0) { // v[x1] + op <= v[x2]
                add(x1, x2, op);
            }
            else if (t1 == 0 && t2 == 1) { // v[x1] + op <= x2
                maxv[x1] = min(maxv[x1], x2 - op);
            }
            else if (t1 == 1 && t2 == 0) { // x1 + op <= v[x2]
                d[x2] = max(d[x2], x1 + op);
            }
            else { // x1 + op <= x2
                if (x1 + op > x2) ok = 0;
            }
        }
        if (!ok) {
            printf("NO
    ");
            return 0;
        }
        int head = 0, tail = 0;
        auto push_back = [&](int x) {
            q[tail ++] = x; if (tail == N) tail = 0;
        };
        auto push_front = [&](int x) {
            if (head == 0) head = N - 1; else head --;
            q[head] = x;
        };
        auto pop = [&]() -> int {
            int t = q[head]; head ++; if (head == N) head = 0;
            return t;
        };
        rep(i, 1, k) inq[i] = 1, push_back(i);
        auto spfa = [&]() -> bool {
            while (head != tail) {
                int u = pop(); inq[u] = 0;
                for (int i = ehead[u]; i; i = e[i].next) {
                    int v = e[i].v;
                    if (d[v] < d[u] + e[i].cost) {
                        d[v] = d[u] + e[i].cost;
                        if (d[v] > maxv[v]) return 0;
                        if (!inq[v]) {
                            inq[v] = 1;
                            cnt[v] ++;
                            if (cnt[v] >= n) return 0;
                            // if (e[i].cost == 0) push_front(v);
                            // else push_back(v);
                            push_front(v);
                        }
                    }
                }
            }
            return 1;
        };
        bool flag = spfa();
        if (!flag) {
            printf("NO
    "); return 0;
        }
        printf("YES
    ");
        rep(i, 1, k) printf("%d
    ", d[i]);
    }
    /*
    2 2
    1 0 1 0 2
    0 0 2 0 1
    3 2 
    1 0 1 0 2 
    0 1 5 0 1 
    0 0 2 1 7
    */

     J.Civilization

    细节很多的网络流,注意到城市很少,只需要枚举哪些城市一定被打了

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i, j, k) for (int i = int(j); i <= int(k); ++ i)
    #define dwn(i, j, k) for (int i = int(j); i >= int(k); -- i)
    typedef long long LL;
    typedef pair<int, int> P;
    typedef vector<int> VI;
    typedef vector<P> VII;
    const int MaxNode = 10000;
    const int MaxEdge = 100000;
    const int INF = 1e9;
    int n, m, C, H, W;
    struct Civi{
        int x, y, p;
        void read2() { scanf("%d%d", &x, &y); }
        void read3() { scanf("%d%d%d", &x, &y, &p); }
    }city[10], cata[110], mount[1010];
    int g[10]; // 连着T的城市的边的的编号
    int cnt = 0; map<P, int> mp; bool ban[MaxNode], can[MaxNode];
    P pos[MaxNode];
    int getX(int x, int y) { // 离散化平面上的点
        if (mp.count(P(x, y))) return mp[P(x, y)]; 
        pos[++cnt] = P(x, y);
        return mp[P(x, y)] = cnt;
    }
    int vis1[MaxNode][10], vis2[MaxNode], dx[6] = {0, 1, 1, 0, -1, -1}, dy[6] = {1, 0, -1, -1, 0, 1};
    struct Network {
        int n, etot = 1;
        int d[MaxNode];      // 层次图标号
        int head[MaxNode];
        int cur[MaxNode];
        struct Edge {
            int to, next, cap;
        }e[MaxEdge], e2[MaxEdge];
        void add(int u, int v, int w) {
            etot ++; e[etot].to = v; e[etot].next = head[u]; e[etot].cap = w; head[u] = etot; 
            etot ++; e[etot].to = u; e[etot].next = head[v]; e[etot].cap = 0; head[v] = etot;
        }   
        bool bfs(int src, int dest) {
            rep(i, 0, n) d[i] = 0;
            d[src] = 1; 
            cur[src] = head[src];
            queue<int> Q;
            Q.push(src);
            while (!Q.empty()) {
                int r = Q.front(); Q.pop();
                for (int i = head[r]; i; i = e[i].next) {
                    int v = e[i].to;
                    if (e[i].cap && !d[v]) {
                        d[v] = d[r] + 1; 
                        cur[v] = head[v];
                        Q.push(v);
                    }
                }
            } 
            return d[dest];
        }   
        int dfs(int u, int dest, int a) {
            if (u == dest || !a) return a;
            int flow = 0, f, v;
            for (int &i = cur[u]; i; i = e[i].next) {
                v = e[i].to;
                if (d[v] == d[u] + 1 && (f = dfs(v, dest, min(a, e[i].cap) ) ) > 0) {
                    e[i].cap -= f;
                    e[i ^ 1].cap += f;
                    a -= f;
                    flow += f;
                    if (!a) break;
                }
            }
            return flow;
        }
        int dinic(int src, int dest) {
            int flow = 0;
            while (bfs(src, dest)) flow += dfs(src, dest, INF);
            return flow;
        }
        void solve(int S, int T, int n, int cityNum, int cataNum) {
            this -> n = n;
            rep(i, 2, etot) e2[i] = e[i];
    
            static int mask[20], maskSize[20];
            rep(i, 1, (1 << cityNum) - 1) mask[i] = i, maskSize[i] = maskSize[i ^ (i & -i)] + 1;
            sort(mask, mask + (1 << cityNum), [&](int i, int j){
                return maskSize[i] > maskSize[j];
            });
            int ansMask = -1;
            for (int i = 0; i < (1 << n); ++ i) {
                int cityMask = mask[i];
                rep(j, 2, etot) e[j] = e2[j];
                int flow = 0;
                rep(j, 1, cityNum) 
                    if (((cityMask >> (j - 1)) & 1) == 0) e[g[j]].cap = 0;
                    else flow += e[g[j]].cap;
                // cout << "??
    ";
                if (dinic(S, T) == flow) {
                    ansMask = cityMask;
                    break;
                }    
            }
            printf("%d
    ", maskSize[ansMask]);
    
            static int m1[MaxNode], m2[MaxNode];
            for (int i = 2; i <= etot; i += 2) {
                int from = e[i ^ 1].to, to = e[i].to;
                if (e[i].cap) continue; 
                if (from >= 1 + cityNum && from <= cityNum + cataNum)
                    m1[from - cityNum] = (to - cityNum - cataNum + 1) / 2;
                if (to >= 1 && to <= cityNum) 
                    m2[(from - cityNum - cataNum + 1) / 2] = to;
            }
            // 防止一个炮车不移动,另外一个炮车挪动到这个位置后位置冲突
            for (;;) {
                bool flag = 1;
                for (int i = 1; i <= cataNum && flag; ++ i) {
                    if (!m1[i]) 
                        for (int j = 1; j <= cataNum && flag; ++ j)
                            if (m1[j] && m1[j] == getX(cata[i].x, cata[i].y)) {
                                flag = 0;
                                m1[i] = m1[j];
                                m1[j] = 0;
                            }
                }
                if (flag) break;
            }
            rep(i, 1, cataNum) {
                if (!m1[i]) printf("%d %d %d
    ", cata[i].x, cata[i].y, 0);
                else printf("%d %d %d
    ", pos[m1[i]].first, pos[m1[i]].second, m2[m1[i]]);
            }
    
        }
    }net;
    void dfs(int x, int y, int d, int col, int op) {
        // op = 0 -- 
        if (x < 0 || x >= W || y < 0 || y >= H) return;
        int u = getX(x, y);
        if (vis1[u][d] == col) return;
        vis1[u][d] = col; 
        if (op && ban[u]) return;
        if (vis2[u] != col) { // 判断这个点是否被搜素过
            // if (col == 3) cout << x << ' ' << y << '
    ';
            if (op == 0) {
                net.add(n + m + 2 * u, col, 1);
                can[u] = 1;
            }
            else if (can[u]) net.add(col, n + m + 2 * u - 1, 1); // 只有当这个点可以攻击到目标点,才加边
            vis2[u] = col;
        }
        if (!d) return;
        rep(i, 0, 5) dfs(x + dx[i], y + dy[i], d - 1, col, op);
    }
    
    int main() {
        scanf("%d%d", &W, &H);
        scanf("%d", &n);
        rep(i, 1, n) city[i].read3(), ban[getX(city[i].x, city[i].y)] = 1;
        scanf("%d", &m);
        rep(i, 1, m) cata[i].read3();
        scanf("%d", &C);
        rep(i, 1, C) mount[i].read2(), ban[getX(mount[i].x, mount[i].y)] = 1;
        rep(i, 1, n) dfs(city[i].x, city[i].y, 2, i, 0);
        rep(i, 1, m) dfs(cata[i].x, cata[i].y, cata[i].p - 1, n + i, 1);
        int S = n + m + 2 * cnt + 1, T = S + 1;
        rep(i, 1, m) net.add(S, i + n, 1); // 每个炮车最多打一个城市
        rep(i, 1, n) net.add(i, T, city[i].p), g[i] = net.etot - 1; // 每个城市有city[i].p的血
        rep(i, 1, cnt) net.add(n + m + 2 * i - 1, n + m + 2 * i, 1); // 每个位置最多停一辆炮车
        net.solve(S, T, T, n, m);
    }
    /*
    10 3
    2
    3 1 2
    9 1 1
    3
    1 1 1
    6 1 2
    7 0 3
    3
    2 1 
    7 1
    8 0
    */
  • 相关阅读:
    关于开发 Web AI 的思考(kendryte K210)
    怪不得我说,这几个月的代码数据都跑哪里去了....
    在 Android 上使用蓝牙作为主机进行一对多从机传输数据的实测,理论 5
    写了一下 micropython 的文件系统单元测试
    mark 自己未来要写一下,蓝牙主机一对多从机和 K210 的网络通信优化过程。
    VUE实现Studio管理后台(五):手风琴式折叠组件(Accordion)
    VUE实现Studio管理后台(四):状态模式实现窗口停靠,灵动、自由
    VUE实现Studio管理后台(三):支持多语言国际化(vue-i18n)
    VUE实现Studio管理后台(二):Slot实现选项卡tab切换效果,可自由填装内容
    VUE实现Studio管理后台(一):鼠标拖放改变窗口大小
  • 原文地址:https://www.cnblogs.com/tempestT/p/10705565.html
Copyright © 2020-2023  润新知