Submission #1219790

#TimeUsernameProblemLanguageResultExecution timeMemory
1219790AdnanboiTug of War (BOI15_tug)C++20
0 / 100
3094 ms6736 KiB
#include <bits/stdc++.h>
using namespace std;

const int INF = 1e9;

struct Edge {
    int to, rev, cap, cost;
    Edge(int t, int r, int ca, int co): to(t), rev(r), cap(ca), cost(co) {}
};

class MinCostMaxFlow {
public:
    int n;
    vector<vector<Edge>> g;
    vector<int> dist, inqueue;
    vector<int> prev, preve;

    MinCostMaxFlow(int _n): n(_n), g(_n), prev(_n), preve(_n), dist(_n), inqueue(_n) {}

    void addEdge(int from, int to, int cap, int cost) {
        Edge e1(to, g[to].size(), cap, cost);
        Edge e2(from, g[from].size(), 0, -cost);
        g[from].push_back(e1);
        g[to].push_back(e2);
    }

    pair<int, int> flow(int s, int t, int maxf) {
        int flow = 0, cost = 0;
        while (true) {
            fill(dist.begin(), dist.end(), INF);
            fill(inqueue.begin(), inqueue.end(), false);
            queue<int> q;
            dist[s] = 0;
            q.push(s);
            inqueue[s] = true;

            while (!q.empty()) {
                int v = q.front(); q.pop();
                inqueue[v] = false;
                for (int i = 0; i < g[v].size(); ++i) {
                    Edge &e = g[v][i];
                    if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
                        dist[e.to] = dist[v] + e.cost;
                        prev[e.to] = v;
                        preve[e.to] = i;
                        if (!inqueue[e.to]) {
                            q.push(e.to);
                            inqueue[e.to] = true;
                        }
                    }
                }
            }
            if (dist[t] == INF) break;
            int d = maxf - flow;
            for (int v = t; v != s; v = prev[v])
                d = min(d, g[prev[v]][preve[v]].cap);
            flow += d;
            cost += d * dist[t];
            for (int v = t; v != s; v = prev[v]) {
                Edge &e = g[prev[v]][preve[v]];
                e.cap -= d;
                g[v][e.rev].cap += d;
            }
        }
        return {flow, cost};
    }
};

int main() {
    int N, K;
    cin >> N >> K;

    int totalStrength = 0;
    vector<pair<int, int>> lr(2*N);
    vector<int> s(2*N);

    for (int i = 0; i < 2*N; ++i) {
        int l, r, si;
        cin >> l >> r >> si;
        lr[i] = {l, r};
        s[i] = si;
        totalStrength += si;
    }

    const int SRC = 2*N + 2*N;
    const int SINK = SRC + 1;
    const int TOTAL = SINK + 1;

    MinCostMaxFlow mcmf(TOTAL);

    // Source -> Players
    for (int i = 0; i < 2*N; ++i)
        mcmf.addEdge(SRC, i, 1, 0);

    // Players -> Left/Right Positions
    for (int i = 0; i < 2*N; ++i) {
        auto [l, r] = lr[i];
        mcmf.addEdge(i, 2*N + (l-1), 1, s[i]);     // left team adds strength
        mcmf.addEdge(i, 2*N + N + (r-1), 1, -s[i]); // right team subtracts strength
    }

    // Positions -> Sink
    for (int i = 0; i < N; ++i)
        mcmf.addEdge(2*N + i, SINK, 1, 0);
    for (int i = 0; i < N; ++i)
        mcmf.addEdge(2*N + N + i, SINK, 1, 0);

    auto [flow, cost] = mcmf.flow(SRC, SINK, 2*N);
    if (flow != 2*N) {
        cout << "NO\n";
        return 0;
    }

    int sumLeft = (totalStrength + cost) / 2;
    int sumRight = totalStrength - sumLeft;
    if (abs(sumLeft - sumRight) <= K)
        cout << "YES\n";
    else
        cout << "NO\n";

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...