Submission #1268060

#TimeUsernameProblemLanguageResultExecution timeMemory
1268060rtriTug of War (BOI15_tug)C++20
0 / 100
38 ms5600 KiB
#include <bits/stdc++.h>
using namespace std;

typedef long long int ll;

int n, k;
vector<int> used;
vector<pair<int, int>> positions;
vector<ll> strengths;
vector<unordered_set<int>> lefts, rights;
vector<bool> lfilled, rfilled;

int get_not(unordered_set<int> as, int b) {
  if (as.size() != 2)
    assert(false);
  for (auto a : as)
    if (a != b)
      return a;
  assert(false);
}

ll cycle(int i, bool is_left, int start_idx = -1) {
  if (start_idx == i)
    return 0;
  if (start_idx == -1)
    start_idx = i;

  used[i] = start_idx;

  if (is_left) {
    int forced = get_not(lefts[positions[i].first], i);
    return strengths[i] + cycle(forced, !is_left, start_idx);
  } else {
    int forced = get_not(rights[positions[i].second], i);
    return cycle(forced, !is_left, start_idx);
  }
}

int forced_fill(int i) {
  if (used[i] != -1) {
    cout << "NO" << endl;
    exit(0);
  }

  auto [currl, currr] = positions[i];
  if (lfilled[currl] && rfilled[currr]) {
    cout << "NO" << endl;
    exit(0);
  } else if (lfilled[currl]) {
    rfilled[currr] = 1;
    used[i] = 1;
    lefts[currl].erase(i);
    rights[currr].erase(i);
    return 0;
  } else if (rfilled[currr]) {
    lfilled[currl] = 1;
    used[i] = 1;
    lefts[currl].erase(i);
    rights[currr].erase(i);
    return strengths[i];
  } else {
    if (lefts[currl].size() == 1 && rights[currr].size() == 1) {
      cout << "NO" << endl;
      exit(0);
    } else if (lefts[currl].size() == 1) {
      lfilled[currl] = 1;
      used[i] = 1;
      lefts[currl].erase(i);
      rights[currr].erase(i);
      if (rights[currr].size() == 1)
        return strengths[i] + forced_fill(*rights[currr].begin());
    } else if (rights[currl].size() == 1) {
      rfilled[currr] = 1;
      used[i] = 1;
      lefts[currl].erase(i);
      rights[currr].erase(i);
      if (lefts[currl].size() == 1)
        return forced_fill(*lefts[currl].begin());
    }
  }

  return 0;
}

int main() {
  cin >> n >> k;

  ll total_strength = 0;
  positions.resize(2 * n);
  strengths.resize(2 * n);
  lefts.resize(n);
  rights.resize(n);
  lfilled.resize(n);
  rfilled.resize(n);
  for (int i = 0; i < n * 2; i++) {
    int l, r, s;
    cin >> l >> r >> s;
    l--;
    r--;
    positions[i] = {l, r};
    strengths[i] = s;
    lefts[l].insert(i);
    rights[r].insert(i);
    total_strength += s;
  }

  ll base = 0;
  used.resize(2 * n, -1);
  for (int i = 0; i < 2 * n; i++) {
    if (used[i] != -1)
      continue;
    base += forced_fill(i);
  }

  for (int i = 0; i < n; i++) {
    int ls = lefts[i].size(), rs = rights[i].size();
    if ((!lfilled[i] && ls != 2) || (!rfilled[i] && rs != 2)) {
      cout << "NO" << endl;
      return 0;
    }
  }

  vector<ll> knapsack;
  for (int i = 0; i < 2 * n; i++) {
    if (used[i] != -1)
      continue;

    int r = cycle(i, false);
    int l = cycle(i, true);
    base += min(r, l);
    knapsack.push_back(max(r, l) - min(r, l));
  }

  cerr << "TOTAL " << total_strength << endl;
  cerr << "BASE " << base << endl;
  for (int i = 0; i < knapsack.size(); i++)
    cerr << knapsack[i] << " ";
  cerr << endl;

  bitset<50000> reach;
  reach[base] = 1;
  for (int elem : knapsack)
    reach |= reach << elem;

  for (int i = (total_strength - k + 1) / 2; i <= (total_strength + k) / 2;
       i++) {
    assert(abs(i - (total_strength - i)) <= k);
    if (reach[i]) {
      cout << "YES" << endl;
      return 0;
    }
  }

  cout << "NO" << endl;
  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...