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
*/
原文地址:https://www.cnblogs.com/tempestT/p/10705565.html