Submission #578101

# Submission time Handle Problem Language Result Execution time Memory
578101 2022-06-16T04:57:04 Z Kanon Simurgh (IOI17_simurgh) C++14
0 / 100
1 ms 468 KB
#include <bits/stdc++.h>
#include "simurgh.h"

using namespace std;

template <typename A, typename B>
string to_string(pair<A, B> p);

template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p);

template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p);

string to_string(const string& s) {
  return '"' + s + '"';
}

string to_string(const char* s) {
  return to_string((string) s);
}

string to_string(bool b) {
  return (b ? "true" : "false");
}

string to_string(vector<bool> v) {
  bool first = true;
  string res = "{";
  for (int i = 0; i < static_cast<int>(v.size()); i++) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(v[i]);
  }
  res += "}";
  return res;
}

template <size_t N>
string to_string(bitset<N> v) {
  string res = "";
  for (size_t i = 0; i < N; i++) {
    res += static_cast<char>('0' + v[i]);
  }
  return res;
}

template <typename A>
string to_string(A v) {
  bool first = true;
  string res = "{";
  for (const auto &x : v) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(x);
  }
  res += "}";
  return res;
}

template <typename A, typename B>
string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";
}

template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}

void debug_out() { cerr << endl; }

template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}

#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__);

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> n1, vector<int> n2) {
  int m = n1.size();
  vector<vector<int>> g(n);
  for (int i = 0; i < m; i++) {
    g[n1[i]].push_back(i);
    g[n2[i]].push_back(i);
  }

  vector<int> par(n, -1);
  vector<int> dep(n);
  vector<int> was(n);
  function<void(int, int)> dfs = [&](int v, int p) {
    was[v] = 1;
    par[v] = p;
    for (int e : g[v]) {
      if (e == p) {
        continue;
      }
      int u = n1[e] ^ n2[e] ^ v;
      if (was[u]) {
        continue;
      }
      dep[u] = dep[v] + 1;
      dfs(u, e);
    }
  };
  dfs(0, -1);

  set<int> tree_edges;
  for (int i = 0; i < n; i++) {
    if (par[i] != -1) {
      tree_edges.insert(par[i]);
    }
  }

  vector<int> ret(m, -1);
  auto royal = [&](set<int> S) {
    vector<int> p;
    for (int i : S) {
      p.push_back(i);
    }
    assert((int) p.size() == n - 1);
    return count_common_roads(p);
  };



  {
    auto handle_cycle = [&](vector<int> c) {
      assert(c.size() >= 3);
      set<int> S = tree_edges;

      int e = -1, ve = -1;
      for (int i : c) {
        if (ret[i] != -1) {
          e = i;
          ve = ret[i];
        }
        S.insert(i);
      }
      assert((int) S.size() == n);

      if (e != -1) {
        S.erase(e);
        int vS = royal(S) + ve;
        S.insert(e);
        for (int i : c) {
          if (ret[i] != -1) {
            continue;
          }
          S.erase(i);
          ret[i] = vS - royal(S);
          S.insert(i);
        }
      } else {
        vector<int> val;
        for (int i : c) {
          S.erase(i);
          val.push_back(royal(S));
          S.insert(i);
        }
        int mx = *max_element(val.begin(), val.end());
        for (int i = 0; i < (int) c.size(); i++) {
          if (val[i] == mx) {
            ret[c[i]] = 0;
          } else {
            ret[c[i]] = 1;
          }
        }
      }
    };

    function<vector<int>(int)> calc = [&](int v) {
      vector<int> cycle;
      int highest = dep[v] - 1;
      int back_ed = -1;
      for (int e : g[v]) {
        int u = n1[e] ^ n2[e] ^ v;
        if (dep[u] < highest) {
          highest = dep[u];
          back_ed = e;
        }
      }

      if (back_ed != -1) {
        int cur = v;
        while (highest < dep[cur]) {
          int e = par[cur];
          cycle.push_back(e);
          cur = n1[e] ^ n2[e] ^ cur;
        }
        cycle.push_back(back_ed);
      }

      for (int ed : g[v]) {
        int u = n1[ed] ^ n2[ed] ^ v;
        if (ed != par[u]) {
          continue;
        }
        vector<int> now = calc(u);
        if (now.empty()) {
          continue;
        }
        int val = n;
        for (int e : now) {
          val = min(val, min(dep[n1[e]], dep[n2[e]]));
        }
        if (val < highest) {
          cycle = now;
          highest = val;
        }
      }

      if (!cycle.empty()) {
        handle_cycle(cycle);
      } else {
        if (par[v] != -1) {
          ret[par[v]] = 1;
        }
      }
      return cycle;
    };

    calc(0);
  }






  auto make_tree = [&](vector<int> edges) {
    dsu d(n);
    set<int> S;
    int v = 0;
    for (int e : edges) {
      assert(d.unite(n1[e], n2[e]));
      S.insert(e);
    }
    for (int e : tree_edges) {
      assert(ret[e] != -1);
      if (d.unite(n1[e], n2[e])) {
        S.insert(e);
        v += ret[e];
      }
    }
    return make_pair(S, v);
  };

  function<void(set<int>)> calc = [&](set<int> nodes) {
    if (nodes.size() == 1) {
      return;
    }

    int divide = -1;
    for (int e : tree_edges) {
      if (nodes.find(n1[e]) != nodes.end() && nodes.find(n2[e]) != nodes.end()) {
        divide = e;
      }
    }
    assert(divide != -1);

    dsu d(n);
    for (int e : tree_edges) {
      if (e != divide) {
        d.unite(n1[e], n2[e]);
      }
    }

    int a = n1[divide], b = n2[divide];
    assert(d.get(a) != d.get(b));
    set<int> A, B;
    for (int i : nodes) {
      if (d.get(a) == d.get(i)) {
        A.insert(i);
      } else {
        assert(d.get(b) == d.get(i));
        B.insert(i);
      }
    }

    calc(A); calc(B);

    if (A.size() > B.size()) {
      swap(A, B);
    }
    vector<int> order;

    for (int v : A) {
      for (int e : g[v]) {
        int u = n1[e] ^ n2[e] ^ v;
        if (B.find(u) == B.end() || ret[e] != -1) {
          continue;
        }
        order.push_back(e);
      }
    }

    vector<vector<int>> forest;
    set<pair<int, int>> dead;
    for (int i = 0; i < (int) order.size(); i++) {
      dead.insert({i, order[i]});
    }

    while (!dead.empty()) {
      vector<int> now;
      d = dsu(n);
      vector<pair<int, int>> rev;
      for (auto pe : dead) {
        int e = pe.second;
        if (ret[e] != -1) {
          continue;
        }
        if (d.unite(n1[e], n2[e])) {
          now.push_back(e);
          rev.push_back(pe);
        }
      }
      for (auto pe : rev) {
        dead.erase(pe);
      }
      forest.push_back(now);
    }

    for (vector<int> edges : forest) {
      int sz = edges.size();
      auto pi = make_tree(edges);
      int Valued = royal(pi.first) - pi.second;
      if (Valued == 0) {
        for (int e : edges) {
          ret[e] = 0;
        }
        continue;
      }

      function<void(int, int, int)> solve = [&](int L, int R, int val) {
        assert(val > 0);
        if (L == R) {
          assert(val <= 1);
          assert(ret[edges[L]] == val || ret[edges[L]] == -1);
          ret[edges[L]] = val;
          return;
        }

        int mid = (L + R) >> 1;
        vector<int> now;
        for (int i = L; i <= mid; i++) {
          now.push_back(edges[i]);
        }

        auto Pi = make_tree(now);
        int t = royal(Pi.first) - Pi.second;

        if (val - t > 0) {
          solve(mid + 1, R, val - t);
        } else {
          for (int i = mid + 1; i <= R; i++) {
            assert(ret[edges[i]] < 1);
            ret[edges[i]] = 0;
          }
        }

        if (t > 0) {
          solve(L, mid, t);
        } else {
          for (int i = L; i <= mid; i++) {
            assert(ret[edges[i]] < 1);
            ret[edges[i]] = 0;
          }
        }
      };

      solve(0, sz - 1, Valued);
    }

  };

  set<int> nodes;
  for (int i = 0; i < n; i++) {
    nodes.insert(i);
  }

  calc(nodes);

  vector<int> res;
  for (int i = 0; i < m; i++) {
    assert(ret[i] != -1);
    if (ret[i] == 1) {
      res.push_back(i);
    }
  }

  assert((int) res.size() == n - 1);

  return res;

}
# Verdict Execution time Memory Grader output
1 Runtime error 1 ms 428 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 1 ms 428 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 1 ms 428 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 0 ms 212 KB correct
2 Runtime error 1 ms 468 KB Execution killed with signal 6
3 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 1 ms 428 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -