Submission #1052763

#TimeUsernameProblemLanguageResultExecution timeMemory
1052763MilosMilutinovicSimurgh (IOI17_simurgh)C++14
100 / 100
149 ms5028 KiB
#include "simurgh.h"
#include <bits/stdc++.h>

using namespace std;

class dsu {
 public:
  vector<int> p;
  int n;

  dsu(int _n) : n(_n) {
    p.resize(n);
    iota(p.begin(), p.end(), 0);
  }

  inline int get(int x) {
    return (x == p[x] ? x : (p[x] = get(p[x])));
  }

  inline bool unite(int x, int y) {
    x = get(x);
    y = get(y);
    if (x != y) {
      p[x] = y;
      return true;
    }
    return false;
  }
};

vector<int> find_roads(int n, vector<int> u, vector<int> v) {
  int m = (int) u.size();
  vector<vector<int>> g(n);
  for (int i = 0; i < m; i++) {
    g[u[i]].push_back(i);
    g[v[i]].push_back(i);
  }
  dsu d(n);
  vector<int> tree;
  for (int i = 0; i < m; i++) {
    if (d.unite(u[i], v[i])) {
      tree.push_back(i);
    }
  }
  vector<vector<int>> t(n);
  for (int i : tree) {
    t[u[i]].push_back(i);
    t[v[i]].push_back(i);
  }
  int cnt = count_common_roads(tree);
  const int L = 20;
  vector<vector<int>> pr(n, vector<int>(L));
  vector<int> dep(n);
  vector<int> id(n);
  function<void(int, int)> Dfs = [&](int x, int px) {
    dep[x] = dep[px] + 1;
    pr[x][0] = px;
    for (int i = 1; i < L; i++) {
      pr[x][i] = pr[pr[x][i - 1]][i - 1];
    }
    for (int e : t[x]) {
      int y = (x ^ u[e] ^ v[e]);
      if (y == px) {
        continue;
      }
      id[y] = e;
      Dfs(y, x);
    }
  };
  Dfs(0, 0);
  auto LCA = [&](int x, int y) {
    if (dep[x] > dep[y]) {
      swap(x, y);
    }
    for (int i = L - 1; i >= 0; i--) {
      if (dep[pr[y][i]] >= dep[x]) {
        y = pr[y][i];
      }
    }
    if (x == y) {
      return x;
    }
    for (int i = L - 1; i >= 0; i--) {
      if (pr[x][i] != pr[y][i]) {
        x = pr[x][i];
        y = pr[y][i];
      }
    }
    return pr[x][0];
  };
  vector<int> state(m, 2);
  for (int i : tree) {
    state[i] = -1;
  }
  for (int i = 0; i < m; i++) {
    if (state[i] != 2) {
      continue;
    }
    vector<int> edges;
    int z = LCA(u[i], v[i]);
    for (int x = u[i]; x != z; x = pr[x][0]) {
      edges.push_back(id[x]);
    }
    for (int x = v[i]; x != z; x = pr[x][0]) {
      edges.push_back(id[x]);
    }
    vector<pair<int, int>> a;
    for (int e : edges) {
      if (state[e] != -1) {
        continue;
      }
      vector<int> qv(1, i);
      for (int i : tree) {
        if (i != e) {
          qv.push_back(i);
        }
      }
      a.emplace_back(count_common_roads(qv), e);
    }
    if (a.empty()) {
      continue;
    }
    for (auto& p : a) {
      if (p.first == cnt - 1) {
        state[i] = 0;
      }
      if (p.first == cnt + 1) {
        state[i] = 1;
      }
    }
    if (state[i] == 2) {
      for (int e : edges) {
        if (state[e] == -1) {
          continue;
        }
        vector<int> qv(1, i);
        for (int i : tree) {
          if (i != e) {
            qv.push_back(i);
          }
        }
        state[i] = (state[e] ^ (cnt != count_common_roads(qv) ? 1 : 0));
        break;
      }
      if (state[i] == 2) {
        state[i] = 0;
      }
    }
    for (auto& p : a) {
      state[p.second] = (state[i] ^ (cnt != p.first ? 1 : 0));
    }
  }
  for (int e : tree) {
    if (state[e] == -1) {
      state[e] = 1;
    }
  }
  vector<int> deg(n);
  for (int i = 0; i < n; i++) {
    dsu d(n);
    vector<int> qv;
    for (int e : g[i]) {
      qv.push_back(e);
      d.unite(u[e], v[e]);
    }
    int ft = 0;
    for (int e : tree) {
      if (d.unite(u[e], v[e])) {
        qv.push_back(e);
        ft += state[e];
      }
    }
    deg[i] = count_common_roads(qv) - ft;
  }
  vector<int> que;
  for (int i = 0; i < n; i++) {
    if (deg[i] == 1) {
      que.push_back(i);
    }
  }
  vector<bool> was(n);
  vector<int> res;
  for (int b = 0; b < (int) que.size(); b++) {
    int i = que[b];
    if (i == 0) {
      continue;
    }
    was[i] = true;
    vector<int> f;
    for (int e : g[i]) {
      if (!was[u[e] ^ v[e] ^ i]) {
        f.push_back(e);
      }
    }
    int low = 0, high = (int) f.size() - 1, who = -1;
    while (low <= high) {
      int mid = (low + high) >> 1;
      vector<int> qv;
      dsu d(n);
      for (int j = 0; j <= mid; j++) {
        qv.push_back(f[j]);
        d.unite(u[f[j]], v[f[j]]);  
      }
      int ft = 0;
      for (int e : tree) {
        if (d.unite(u[e], v[e])) {
          qv.push_back(e);
          ft += state[e];
        }
      }
      if (count_common_roads(qv) - ft > 0) {
        who = mid;
        high = mid - 1;
      } else {
        low = mid + 1;
      }
    }
    res.push_back(f[who]);
    int j = (u[f[who]] ^ v[f[who]] ^ i);
    deg[j] -= 1;
    if (deg[j] == 1) {
      que.push_back(j);
    }
  }
  return res;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...