Submission #1323727

#TimeUsernameProblemLanguageResultExecution timeMemory
1323727viyeuquadamdauTug of War (BOI15_tug)C++20
100 / 100
110 ms8856 KiB
// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/allocator.h>
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx,avx2,popcnt,lzcnt")

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define vec vector
#define PB push_back
#define all(x) x.begin(), x.end()
#define F first
#define S second
using pii = pair<int,int>;

int n, k;

// dynamic containers (will be resized after reading n)
vec<vec<pii>> gr;
vec<int> tin;
vec<pii> par;
vec<int> A, B, S;
vec<char> in_cycle;

int tplt = 0, numdfs = 0;
vec<pii> cycle;

void dfs(int u, int p = 0){
    tin[u] = ++numdfs;
    for (pii &v: gr[u]) if (v.S != p) {
        if (!tin[v.F]) {
            par[v.F] = {u, v.S};
            dfs(v.F, v.S);
        } else if (tin[v.F] < tin[u]) {
            cycle.clear();
            cycle.PB({v.F, v.S});
            in_cycle[v.F] = 1;
            int t = u;
            while (t != v.F) {
                in_cycle[t] = 1;
                cycle.PB({t, par[t].second});
                t = par[t].first;
            }
        }
    }
}

void dfs_tree(int u, int val, int p = 0){
    if (u <= n) {
        A[tplt] += val;
        B[tplt] += val;
    }
    for (pii v: gr[u]) if (v.F != p && !in_cycle[v.F]) {
        dfs_tree(v.F, S[v.S], u);
    }
}

void process_cycle(){
    for (pii &i : cycle) {
        int u = i.F;
        for (pii &v : gr[u]) if (!in_cycle[v.F]) dfs_tree(v.F, S[v.S], u);
    }
    int len = (int)cycle.size();
    for (int i = 0; i < len; ++i) {
        int val = S[cycle[i].S];
        int u = cycle[i].F, v = cycle[(i + 1) % len].F;
        if (u <= n) B[tplt] += val;
        if (v <= n) A[tplt] += val;
    }
}

//
inline void set_bit(vec<uint64_t>& bits, int pos) {
    bits[pos >> 6] |= (1ULL << (pos & 63));
}
inline bool test_bit(const vec<uint64_t>& bits, int pos) {
    return (bits[pos >> 6] >> (pos & 63)) & 1ULL;
}


void shift_or(vec<uint64_t>& dpbits, int shift, int totbits) {
    if (shift == 0) return;
    int L = (int)dpbits.size();
    int wordShift = shift >> 6;
    int bitShift = shift & 63;

    vec<uint64_t> orig = dpbits;
    if (bitShift == 0) {
        for (int i = L - 1; i >= wordShift; --i) {
            dpbits[i] |= orig[i - wordShift];
        }
    } else {
        for (int i = L - 1; i >= wordShift; --i) {
            uint64_t high = orig[i - wordShift] << bitShift;
            uint64_t low = 0;
            if (i - wordShift - 1 >= 0) low = orig[i - wordShift - 1] >> (64 - bitShift);
            dpbits[i] |= (high | low);
        }
    }
   
    int excess = (L << 6) - (totbits + 1);
    if (excess > 0) {
        int last_valid = (totbits) & 63;
        dpbits[L - 1] &= ((last_valid == 63) ? ~0ULL : ((1ULL << (last_valid + 1)) - 1ULL));
    }
}

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

    cin >> n >> k;
    int nodes = 2 * n;
    gr.assign(nodes + 5, {});
    tin.assign(nodes + 5, 0);
    par.assign(nodes + 5, {0, 0});
    A.assign(nodes + 5, 0);
    B.assign(nodes + 5, 0);
    S.assign(nodes + 5, 0);
    in_cycle.assign(nodes + 5, 0);

    int tot = 0;
    for (int i = 1; i <= 2 * n; ++i) {
        int u, v; cin >> u >> v >> S[i];
        gr[u].PB({n + v, i});
        gr[n + v].PB({u, i});
        tot += S[i];
    }

   
    for (int i = 1; i <= nodes; ++i) if (!tin[i]) {
        ++tplt;
        cycle.clear();
        dfs(i);
        process_cycle();
    }

   
    vector<int> freq(tot + 1, 0);
    int base = 0;
    for (int i = 1; i <= tplt; ++i) {
        base += min(A[i], B[i]);
        int diff = abs(A[i] - B[i]);
        if (diff <= tot) freq[diff]++;
    }

    //
    int bitsNeeded = tot;
    int L = (bitsNeeded + 64) / 64;
    vec<uint64_t> dpbits(L, 0ULL);
    set_bit(dpbits, 0);

   
    for (int w = 1; w <= tot; ++w) if (freq[w]) {
        int cnt = freq[w];
        int p = 1;
        while (cnt >= p) {
            int weight = w * p;
            if (weight <= tot) shift_or(dpbits, weight, bitsNeeded);
            cnt -= p;
            p <<= 1;
        }
        if (cnt > 0) {
            int weight = w * cnt;
            if (weight <= tot) shift_or(dpbits, weight, bitsNeeded);
        }
    }

    bool ok = false;
    for (int i = base; i <= tot; ++i) {
        int pos = i - base;
        if (pos <= tot && test_bit(dpbits, pos) && llabs(2LL * i - tot) <= k) {
            ok = true; break;
        }
    }
    if (ok) 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...