QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#225577#6402. MEXimum Spanning TreeYouKn0wWhoTL 684ms9520kbC++235.9kb2023-10-24 20:12:122023-10-24 20:12:13

Judging History

你现在查看的是最新测评结果

  • [2023-10-24 20:12:13]
  • 评测
  • 测评结果:TL
  • 用时:684ms
  • 内存:9520kb
  • [2023-10-24 20:12:12]
  • 提交

answer

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

const int N = 1005, MAX_INDEPENDENT_SET_SIZE = 1005;
using T = pair<int, int>;

struct GroundSetElement {
  int color;
  T edge;
  bool in_independent_set; // if this element is in the IS
  int independent_set_position; // the index of this element in the IS
};

vector<GroundSetElement> elements;
vector<int> independent_set; // stores the indices of the ground set elements

struct GraphicOracle {
  struct GraphBasis {
    vector<int> par, rnk, sz;
    int c;
    GraphBasis(){}
    GraphBasis(int n) : par(n + 1), rnk(n + 1, 0), sz(n + 1, 1), c(n) {
      for (int i = 1; i <= n; ++i) par[i] = i;
    }
    int find(int i) {
      return (par[i] == i ? i : (par[i] = find(par[i])));
    }
    bool same(int i, int j) {
      return find(i) == find(j);
    }
    int get_size(int i) {
      return sz[find(i)];
    }
    int count() {
      return c;    //connected components
    }
    int add_edge(T edge) { // add an independent edge
      auto [i, j] = edge;
      if ((i = find(i)) == (j = find(j))) return -1;
      else --c;
      if (rnk[i] > rnk[j]) swap(i, j);
      par[i] = j;
      sz[j] += sz[i];
      if (rnk[i] == rnk[j]) rnk[j]++;
      return j;
    }
    bool independent_with(T edge) {
      return !same(edge.first, edge.second);
    }
  };
  int n;
  GraphBasis basis; // of independent set
  GraphBasis basis_without[MAX_INDEPENDENT_SET_SIZE + 1];

  GraphicOracle(){}
  GraphicOracle(int n) : n(n) {}

  // can we insert elements[id] without breaking independence?
  bool can_insert(int id) {
    return basis.independent_with(elements[id].edge);
  }

  // can we insert elements[inserted_id] and remove elements[removed_id] 
  // without breaking independence?
  bool can_exchange(int inserted_id, int removed_id) {
    int pos = elements[removed_id].independent_set_position;
    return basis_without[pos].independent_with(elements[inserted_id].edge);
  }

  // prepare the oracle for the current independent set
  void prepare() {
    basis = GraphBasis(n);

    for (int i = 0; i < independent_set.size(); i++) {
      basis_without[i] = GraphBasis(n);
    }

    for (int i = 0; i < independent_set.size(); i++) {
      basis.add_edge(elements[independent_set[i]].edge);
      for (int  j = 0; j < independent_set.size(); j++) {
        if (i != j) basis_without[i].add_edge(elements[independent_set[j]].edge);
      }
    }
  }
}graphic_oracle;


struct ColorfulOracle {
  int color_count;
  vector<bool> color_used;

  ColorfulOracle(int _color_count = 0) {
    color_count = _color_count;
    color_used = vector<bool>(color_count + 1, false);
  }

  // can we insert elements[id] without breaking independence?
  bool can_insert(int id) {
    int inserted_color = elements[id].color;
    return !color_used[inserted_color];
  }

  // can we insert elements[inserted_id] and remove elements[removed_id] 
  // without breaking independence?
  bool can_exchange(int inserted_id, int removed_id) {
    int inserted_color = elements[inserted_id].color;
    int removed_color = elements[removed_id].color;
    if (!color_used[inserted_color]) return true;
    return inserted_color == removed_color;
  }

  // prepare the oracle for the current independent set
  void prepare() {
    for (int c = 0; c < color_count; c++) {
      color_used[c] = false;
    }
    for (auto idx : independent_set) {
      color_used[elements[idx].color] = true;
    }
  }
}colorful_oracle;

// try to increment the size of the independent set
// implementation details: https://codeforces.com/blog/entry/69287#:~:text=Implementation%20and%20complexity
bool augment() {
  // swapping the oracles might run faster
  auto oracle1 = colorful_oracle;
  auto oracle2 = graphic_oracle;
  oracle1.prepare();
  oracle2.prepare();

  const int SOURCE = -1;
  const int NOT_VISITED = -2;
  const int NOT_FOUND = -3;

  int sz = elements.size();
  vector<int> par(sz, NOT_VISITED);
  int endpoint = NOT_FOUND;
  queue<int> q;
  for (int i = 0; i < sz; i++) {
    if (oracle1.can_insert(i)) {
      par[i] = SOURCE;
      q.push(i);
    }
  }
  while (q.size()) {
    int cur = q.front();
    q.pop();
    if (elements[cur].in_independent_set) {
      for (int to = 0; to < sz; to++) {
        if (par[to] != NOT_VISITED) continue;
        if (!oracle1.can_exchange(to, cur)) continue;
        par[to] = cur;
        q.push(to);
      }
    } else {
      if (oracle2.can_insert(cur)) {
        endpoint = cur;
        break;
      }
      for (auto to : independent_set) {
        if (par[to] != NOT_VISITED) continue;
        if (!oracle2.can_exchange(cur, to)) continue;
        par[to] = cur;
        q.push(to);
      }
    }
  }
  if (endpoint == NOT_FOUND) return false;
  do {
    elements[endpoint].in_independent_set ^= true;
    endpoint = par[endpoint];
  } while (endpoint != SOURCE);
  independent_set.clear();
  for (int i = 0; i < sz; i++) {
    if (elements[i].in_independent_set) {
      elements[i].independent_set_position = independent_set.size();
      independent_set.push_back(i);
    }
  }
  return true;
}

int32_t main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n, m; cin >> n >> m;
  int u[m + 1], v[m + 1], w[m + 1], a[m + 1];
  for (int i = 1; i <= m; i++) {
    cin >> u[i] >> v[i] >> w[i];
    a[i] = i;
  }
  sort(a + 1, a + m + 1, [&](int i, int j) {return w[i] < w[j];});
  int ans = 0;
  graphic_oracle = GraphicOracle(n);
  colorful_oracle = ColorfulOracle(n);
  int cur = 0;
  for (int _i = 1; _i <= m; _i++) {
    int i = a[_i];
    if (w[i] > cur) break;
    if (w[i] == cur) ++cur;
    elements.emplace_back();
    elements.back().color = w[i];
    elements.back().edge = T(u[i], v[i]);
    elements.back().in_independent_set = false;
    while (augment());
    if (independent_set.size() != cur) {
      break;
    }
    ans = cur;
  }
  cout << ans << '\n';
  return 0;
}

详细

Test #1:

score: 100
Accepted
time: 1ms
memory: 3772kb

input:

4 4
1 2 0
2 3 1
1 3 1
3 4 2

output:

3

result:

ok 1 number(s): "3"

Test #2:

score: 0
Accepted
time: 684ms
memory: 9520kb

input:

1000 1000
647 790 6
91 461 435
90 72 74
403 81 240
893 925 395
817 345 136
88 71 821
831 962 53
164 270 298
14 550 317
99 580 81
26 477 488
977 474 861
413 483 167
872 675 17
819 327 449
594 242 68
381 983 319
867 582 358
869 225 669
274 352 392
40 388 998
246 477 44
508 979 286
483 776 71
580 438 6...

output:

502

result:

ok 1 number(s): "502"

Test #3:

score: -100
Time Limit Exceeded

input:

900 1000
232 890 107
425 399 19
5 74 753
105 333 163
779 42 582
359 647 524
767 409 48
239 780 443
484 489 546
97 634 562
627 866 714
500 357 590
60 728 591
407 686 210
547 32 370
76 772 500
407 584 772
73 699 69
332 847 516
829 754 727
562 756 678
819 303 128
781 667 263
535 672 767
89 762 216
878 ...

output:


result: