cp-includes

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub rsalesc/cp-includes

:warning: matroid/GraphicMatroid.cpp

Depends on

Required by

Code

#ifndef _LIB_GRAPHIC_MATROID
#define _LIB_GRAPHIC_MATROID
#include <bits/stdc++.h>
#include "Matroid.cpp"
#include "../utils/FastAdj.cpp"

namespace lib {
  using namespace std;
struct GraphicMatroid : Matroid {
  lambda::Map<pair<int, int>> edge;
  FastAdj<pair<int, int>> g;
  vector<int> comp, st, nd, low;
  vector<int> bridges;
  int tempo, comps;
  bool printer = true;

  GraphicMatroid(int n, const lambda::Map<pair<int, int>>& edge_)
    : Matroid(), edge(edge_), g(n, n) {}
  void setup() {
    g.clear();
    g.reserve(ground_set_size());
    for(int i = 0; i < ground_set_size(); i++)
      if(in_I(i)) {
        auto p = edge(i);
        g.add(p.first, {p.second, i});
        g.add(p.second, {p.first, i});
      }
    build_graph();
  }
  void build_graph() {
    int n = g.size();
    comp.assign(n, -1);
    st.assign(n, 0);
    nd.assign(n, 0);
    low.assign(n, 0);
    bridges.assign(ground_set_size(), 0);

    tempo = 0;
    comps = 0;
    for(int i = 0; i < n; i++) {
      if(comp[i] == -1) dfs(i, -1, comps++);
    }
  }
  void dfs(int u, int p, int c) {
    comp[u] = c;
    st[u] = low[u] = tempo++;
    for(auto e : g.n_edges(u)) {
      int v = e.first;
      if(v == p) {
        p = -1;
        continue;
      }
      if(comp[v] != -1) low[u] = min(low[u], st[v]);
      else {
        dfs(v, u, c);
        low[u] = min(low[u], low[v]);
        if(low[v] > st[u]) {
          bridges[e.second] = 1;
        }
      }
    }
    nd[u] = tempo++;
  }
  bool is_bridge(int i) {
    return bridges[i];
  }
  bool is_anc(int u, int v) {
    return st[u] <= st[v] && st[v] <= nd[u];
  }
  bool can_exchange(int i, int j) {
    auto e1 = edge(i);
    auto e2 = edge(j);
    if(st[e1.first] > st[e1.second]) swap(e1.first, e1.second);
    return is_anc(e1.second, e2.first) + is_anc(e1.second, e2.second) == 1;
  }
  bool can_add(int i) {
    auto e = edge(i);
    return comp[e.first] != comp[e.second];
  }
};
} // namespace lib

#endif
#line 1 "matroid/GraphicMatroid.cpp"


#include <bits/stdc++.h>
#line 1 "matroid/Matroid.cpp"


#line 1 "Lambda.cpp"


#line 1 "Traits.cpp"


#line 4 "Traits.cpp"

namespace lib {
using namespace std;
namespace traits {

template <typename...> struct make_void { using type = void; };

template <typename... T> using void_t = typename make_void<T...>::type;

/// keep caide
template <typename Iterator>
using IteratorCategory = typename iterator_traits<Iterator>::iterator_category;

/// keep caide
template <typename Container>
using IteratorCategoryOf = IteratorCategory<typename Container::iterator>;

/// keep caide
template <typename Iterator>
using IteratorValue = typename iterator_traits<Iterator>::value_type;

/// keep caide
template <typename Container>
using IteratorValueOf = IteratorValue<typename Container::iterator>;

/// keep caide
template <typename Iterator>
using IsRandomIterator =
    is_base_of<random_access_iterator_tag, IteratorCategory<Iterator>>;

/// keep caide
template <typename Iterator>
using IsInputIterator =
    is_base_of<input_iterator_tag, IteratorCategory<Iterator>>;

/// keep caide
template <typename Iterator>
using IsBidirectionalIterator =
    is_base_of<bidirectional_iterator_tag, IteratorCategory<Iterator>>;

/// keep caide
template <typename Container>
using HasRandomIterator =
    is_base_of<random_access_iterator_tag, IteratorCategoryOf<Container>>;

/// keep caide
template <typename Container>
using HasInputIterator =
    is_base_of<input_iterator_tag, IteratorCategoryOf<Container>>;

/// keep caide
template <typename Container>
using HasBidirectionalIterator =
    is_base_of<bidirectional_iterator_tag, IteratorCategoryOf<Container>>;
} // namespace traits
} // namespace lib


#line 5 "Lambda.cpp"

namespace lib {
  using namespace std;
namespace lambda {
  using namespace traits;

const auto identity = [](int i) -> int { return i; };
const auto all = [](int i) -> bool { return true; };
const auto none = [](int i) -> bool { return false; };

auto first_n(int n) {
  return [n](int i) -> bool { return i < n; };
}

template<typename F, typename I = int>
using ValueType = decltype(declval<F>()(declval<I>()));

template<typename T>
struct Map {
  std::function<T(int)> f;
  Map() {}
  template<typename F>
  Map(const F& f_) : f(f_) {}
  T operator()(int i) const {
    return f(i);
  }
};

struct Subset;

template<typename T>
struct SubsetMap : Map<T> {
  using Map<T>::operator();
  using Map<T>::f;

  int n;
  SubsetMap() : Map<T>(), n(0) {}
  template<typename F>
  SubsetMap(int n, F && f_) : Map<T>(f_), n(n) {}
  int size() const { return n; }
  int count() const {
    int cnt = 0;
    for(int i = 0; i < n; i++)
      cnt += f(i) != 0;
    return cnt;
  }
  vector<T> operator()() const {
    vector<T> res(n);
    for(int i = 0; i < n; i++)
      res[i] = f(i);
    return res;
  }

  Subset as_subset() const;

  template<typename U = T,
           enable_if_t<is_same<U, bool>::value>* = nullptr>
  SubsetMap<T> operator!() const {
    return SubsetMap<T>(n, [f=f](int i) { return !f(i); });
  }

  template<typename U = T,
           enable_if_t<is_same<U, bool>::value>* = nullptr>
  SubsetMap<T> operator|(const SubsetMap<T>& rhs) const {
    return SubsetMap<T>(n, [f=f, g=rhs.f](int i) { return f(i) || g(i); });
  }

  SubsetMap<T> operator+(const SubsetMap<T>& rhs) const {
    int N = size() + rhs.size();
    return SubsetMap<T>(N, [n=n, f=f, g=rhs.f](int i) {
      return i >= n ? g(i - n) : f(i);
    });
  }

  SubsetMap<T> operator*(const SubsetMap<T>& rhs) const {
    return SubsetMap<T>(n, [f=f, g=rhs.f](int i) {
      return f(g(i));
    });
  }
};

struct Subset {
  mutable vector<int> map;
  Subset() {}
  Subset(const vector<int>& map_) : map(map_) {
  }
  void add(int i) {
    map.push_back(i);
  }
  void pop() { map.pop_back(); }
  void clear() { map.clear(); }
  int size() const { return map.size(); }
  int operator()(int i) const { return map[i]; }
  vector<int> items() const { return map; }

  template<typename F>
  SubsetMap<ValueType<F>> take_from(F && g) const {
    using T = ValueType<F>;
    auto map_ = map;
    return SubsetMap<T>(map.size(), [g, map_](int i) -> T {
      return g(map_[i]);
    });
  }

  Subset take_subset(const Subset& s) const {
    vector<int> res;
    for(int i : items()) {
      res.push_back(s(i));
    }
    return Subset(res);
  }

  SubsetMap<int> take_indices() const {
    return take_from(identity);
  }

  SubsetMap<int> take_inverse(int def = -1) const {
    int n = 0;
    auto it = max_element(map.begin(), map.end());
    if(it != map.end()) n = *it + 1;
    vector<int> inv(n, def);
    for(int i = 0; i < map.size(); i++)
      inv[map[i]] = i;
    return SubsetMap<int>(n, [inv](int i) -> int {
      return inv[i];
    });
  }

  void sort() const {
    std::sort(map.begin(), map.end());
  }

  Subset operator|(const Subset& rhs) const {
    sort();
    rhs.sort();
    vector<int> res;
    res.reserve(size() + rhs.size());
    merge(map.begin(), map.end(), rhs.map.begin(), rhs.map.end(), back_inserter(res));
    auto it = unique(res.begin(), res.end());
    res.resize(it - res.begin());
    return res;
  }
};

template<>
struct Map<bool> {
    std::function<bool(int)> f;
    Map() {}
    template<typename F>
    Map(const F& f_) : f(f_) {}
    bool operator()(int i) const {
      return f(i);
    }

    template <
      typename Iterator,
      typename enable_if<IsInputIterator<Iterator>::value>::type * = nullptr>
    vector<IteratorValue<Iterator>> operator()(Iterator begin, Iterator end) const {
      vector<IteratorValue<Iterator>> res;
      int i = 0;
      for(auto it = begin; it != end; ++it, ++i) {
        if(f(i)) res.push_back(*it);
      }
      return res;
    }
    template <
      typename Container,
      typename enable_if<HasInputIterator<Container>::value>::type * = nullptr>
    vector<IteratorValueOf<Container>> operator()(const Container& c) const {
      return (*this)(c.begin(), c.end());
    }

    Subset subset(int n) const {
      Subset map;
      for(int i = 0; i < n; i++)
        if(f(i)) map.add(i);
      return map;
    }

    template<typename F>
    SubsetMap<ValueType<F>> subset(int n, F && g) const {
      return subset(SubsetMap<ValueType<F>>(n, g));
    }

    template<typename T>
    SubsetMap<T> subset(const SubsetMap<T>& g) const {
      return subset(g.size()).take_from(g);
    }
};

namespace {
template<typename T,
         enable_if_t<is_same<T, bool>::value>* = nullptr>
Subset as_subset_(const SubsetMap<T>& rhs) {
  Subset map;
  for(int i = 0; i < rhs.size(); i++)
    if(rhs(i)) map.add(i);
  return map;
}
template<typename T,
         enable_if_t<!is_same<T, bool>::value>* = nullptr>
Subset as_subset_(const SubsetMap<T>& rhs) {
  Subset map;
  for(int i = 0; i < rhs.size(); i++)
    map.add(rhs(i));
  return map;
}
}


template<typename T>
Subset SubsetMap<T>::as_subset() const {
  return as_subset_(*this);
  
}

using Filter = Map<bool>;
using SubsetFilter = SubsetMap<bool>;

template<typename T>
SubsetMap<T> from_vector(const vector<T>& v) {
  return SubsetMap<T>(v.size(), [v](int i) -> T {
    return v[i];
  });
}

template<typename U, typename F, typename T = ValueType<F, U>>
SubsetMap<T> map_from_vector(const vector<U>& v, const F& f) {
  return SubsetMap<T>(v.size(), [v, f](int i) -> T {
    return f(v[i]);
  });
}

template<typename T>
SubsetFilter filter_from_vector(const vector<T>& v) {
  return SubsetFilter(v.size(), [v](int i) -> bool {
    return v[i];
  });
}

template<typename T>
SubsetFilter filter_from_sparse_vector(const vector<T>& v) {
  return SubsetFilter(v.size(), [v](int i) -> bool {
    return v[i];
  });
}
} // namespace lambda
} // namespace lib


#line 5 "matroid/Matroid.cpp"

namespace lib {
struct Matroid {
  lambda::SubsetFilter I;
  bool in_I(int i) const {
    return I(i);
  }
  vector<bool> get_I() const {
    return I();
  }
  int ground_set_size() const { return I.size(); }

  /** docstring
   * Used to build a Matroid object from an M (independent set provider).
   */ 
  virtual void build(const lambda::SubsetFilter& I_) {
    I = I_;
  }

  void setup() {}
  void setup_graph() {}
  void setup_exchange(int i) {}
  void finish_exchange(int i) {}

  bool can_add(int i) { return false; }
  bool can_exchange(int i, int j) { return false; }

  void print_I() {
    for(int i = 0; i < I.size(); i++) cout << in_I(i) << " ";
    cout << endl;
  }
};
} // namespace lib


#line 1 "utils/FastAdj.cpp"


#line 4 "utils/FastAdj.cpp"

namespace lib {
  using namespace std;
template<typename T>
struct FastAdj {
  int n;
  vector<T> edges;
  vector<int> head, next;
  FastAdj(int n, int cap = 0) : n(n), edges(), head(), next() {
    edges.reserve(cap);
    next.reserve(cap);
    head.assign(n, -1);
  }
  int size() const {
    return n;
  }
  int edge_size() const {
    return edges.size();
  }
  void reserve(int c) {
    edges.reserve(c);
    next.reserve(c);
  }
  void clear() {
    edges.clear();
    next.clear();
    head.assign(n, -1);
  }
  T& add(int u) {
    int K = edges.size();
    next.push_back(head[u]);
    head[u] = K;
    edges.emplace_back();
    return edges.back();
  }
  void add(int u, T v) {
    int K = edges.size();
    next.push_back(head[u]);
    head[u] = K;
    edges.push_back(v);
  }

  class iterator {
  public:
    typedef iterator self_type;
    typedef T value_type;
    typedef T &reference;
    typedef T *pointer;
    typedef std::forward_iterator_tag iterator_category;
    typedef int difference_type;
    iterator(vector<int> *next, vector<T> *edges, int ptr)
        : next_(next), edges_(edges), ptr_(ptr) {}
    self_type operator++() {
      ptr_ = (*next_)[ptr_];
      return *this;
    }
    self_type operator++(int junk) {
      self_type i = *this;
      ptr_ = (*next_)[ptr_];
      return i;
    }
    reference operator*() { return (*edges_)[ptr_]; }
    pointer operator->() { return &(*edges_)[ptr_]; }
    bool operator==(const self_type &rhs) const {
      return ptr_ == rhs.ptr_;
    }
    bool operator!=(const self_type &rhs) const { return !(*this == rhs); }

  private:
    vector<int> *next_;
    vector<T> *edges_;
    int ptr_;
  };

  class const_iterator {
  public:
    typedef const_iterator self_type;
    typedef T value_type;
    typedef T &reference;
    typedef T *pointer;
    typedef std::forward_iterator_tag iterator_category;
    typedef int difference_type;
    const_iterator(vector<int> *next, vector<T> *edges, int ptr)
        : next_(next_), edges_(edges), ptr_(ptr) {}
    self_type operator++() {
      ptr_ = (*next_)[ptr_];
      return *this;
    }
    self_type operator++(int junk) {
      self_type i = *this;
      ptr_ = (*next_)[ptr_];
      return i;
    }
    const value_type &operator*() { return (*edges_)[ptr_]; }
    const value_type *operator->() { return &(*edges_)[ptr_]; }
    bool operator==(const self_type &rhs) const {
      return ptr_ == rhs.ptr_;
    }
    bool operator!=(const self_type &rhs) const { return !(*this == rhs); }

  private:
    vector<int> *next_;
    vector<T> *edges_;
    int ptr_;
  };

  struct iterable {
    vector<int> *next_;
    vector<T> *edges_;
    int head_;

    iterable(vector<int> *next, vector<T> *edges, int head)
        : next_(next), edges_(edges), head_(head) {}

    inline iterator begin() { return iterator(next_, edges_, head_); }
    inline iterator end() { return iterator(next_, edges_, -1); }

    inline const_iterator cbegin() const {
      return const_iterator(next_, edges_, head_);
    }
    inline const_iterator cend() const {
      return const_iterator(next_, edges_, -1);
    }

    inline const_iterator begin() const { return cbegin(); }
    inline const_iterator end() const { return cend(); }
  };

  inline iterable n_edges(int i) { return iterable(&next, &edges, head[i]); }
  inline const iterable n_edges(int i) const {
    return iterable(const_cast<vector<int> *>(&next),
                    const_cast<vector<T> *>(&edges),
                    head[i]);
  }
};
} // namespace lib


#line 6 "matroid/GraphicMatroid.cpp"

namespace lib {
  using namespace std;
struct GraphicMatroid : Matroid {
  lambda::Map<pair<int, int>> edge;
  FastAdj<pair<int, int>> g;
  vector<int> comp, st, nd, low;
  vector<int> bridges;
  int tempo, comps;
  bool printer = true;

  GraphicMatroid(int n, const lambda::Map<pair<int, int>>& edge_)
    : Matroid(), edge(edge_), g(n, n) {}
  void setup() {
    g.clear();
    g.reserve(ground_set_size());
    for(int i = 0; i < ground_set_size(); i++)
      if(in_I(i)) {
        auto p = edge(i);
        g.add(p.first, {p.second, i});
        g.add(p.second, {p.first, i});
      }
    build_graph();
  }
  void build_graph() {
    int n = g.size();
    comp.assign(n, -1);
    st.assign(n, 0);
    nd.assign(n, 0);
    low.assign(n, 0);
    bridges.assign(ground_set_size(), 0);

    tempo = 0;
    comps = 0;
    for(int i = 0; i < n; i++) {
      if(comp[i] == -1) dfs(i, -1, comps++);
    }
  }
  void dfs(int u, int p, int c) {
    comp[u] = c;
    st[u] = low[u] = tempo++;
    for(auto e : g.n_edges(u)) {
      int v = e.first;
      if(v == p) {
        p = -1;
        continue;
      }
      if(comp[v] != -1) low[u] = min(low[u], st[v]);
      else {
        dfs(v, u, c);
        low[u] = min(low[u], low[v]);
        if(low[v] > st[u]) {
          bridges[e.second] = 1;
        }
      }
    }
    nd[u] = tempo++;
  }
  bool is_bridge(int i) {
    return bridges[i];
  }
  bool is_anc(int u, int v) {
    return st[u] <= st[v] && st[v] <= nd[u];
  }
  bool can_exchange(int i, int j) {
    auto e1 = edge(i);
    auto e2 = edge(j);
    if(st[e1.first] > st[e1.second]) swap(e1.first, e1.second);
    return is_anc(e1.second, e2.first) + is_anc(e1.second, e2.second) == 1;
  }
  bool can_add(int i) {
    auto e = edge(i);
    return comp[e.first] != comp[e.second];
  }
};
} // namespace lib
Back to top page