結果

問題 No.1320 Two Type Min Cost Cycle
ユーザー tonegawatonegawa
提出日時 2023-05-04 17:47:48
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 78 ms / 2,000 ms
コード長 56,508 bytes
コンパイル時間 2,979 ms
コンパイル使用メモリ 186,432 KB
実行使用メモリ 5,248 KB
最終ジャッジ日時 2024-11-22 09:36:05
合計ジャッジ時間 4,925 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,248 KB
testcase_01 AC 2 ms
5,248 KB
testcase_02 AC 2 ms
5,248 KB
testcase_03 AC 2 ms
5,248 KB
testcase_04 AC 2 ms
5,248 KB
testcase_05 AC 2 ms
5,248 KB
testcase_06 AC 2 ms
5,248 KB
testcase_07 AC 7 ms
5,248 KB
testcase_08 AC 8 ms
5,248 KB
testcase_09 AC 44 ms
5,248 KB
testcase_10 AC 7 ms
5,248 KB
testcase_11 AC 30 ms
5,248 KB
testcase_12 AC 9 ms
5,248 KB
testcase_13 AC 16 ms
5,248 KB
testcase_14 AC 7 ms
5,248 KB
testcase_15 AC 7 ms
5,248 KB
testcase_16 AC 4 ms
5,248 KB
testcase_17 AC 4 ms
5,248 KB
testcase_18 AC 5 ms
5,248 KB
testcase_19 AC 11 ms
5,248 KB
testcase_20 AC 3 ms
5,248 KB
testcase_21 AC 43 ms
5,248 KB
testcase_22 AC 2 ms
5,248 KB
testcase_23 AC 2 ms
5,248 KB
testcase_24 AC 2 ms
5,248 KB
testcase_25 AC 2 ms
5,248 KB
testcase_26 AC 2 ms
5,248 KB
testcase_27 AC 2 ms
5,248 KB
testcase_28 AC 6 ms
5,248 KB
testcase_29 AC 8 ms
5,248 KB
testcase_30 AC 3 ms
5,248 KB
testcase_31 AC 3 ms
5,248 KB
testcase_32 AC 2 ms
5,248 KB
testcase_33 AC 50 ms
5,248 KB
testcase_34 AC 24 ms
5,248 KB
testcase_35 AC 2 ms
5,248 KB
testcase_36 AC 2 ms
5,248 KB
testcase_37 AC 2 ms
5,248 KB
testcase_38 AC 3 ms
5,248 KB
testcase_39 AC 2 ms
5,248 KB
testcase_40 AC 2 ms
5,248 KB
testcase_41 AC 2 ms
5,248 KB
testcase_42 AC 2 ms
5,248 KB
testcase_43 AC 8 ms
5,248 KB
testcase_44 AC 5 ms
5,248 KB
testcase_45 AC 18 ms
5,248 KB
testcase_46 AC 3 ms
5,248 KB
testcase_47 AC 37 ms
5,248 KB
testcase_48 AC 7 ms
5,248 KB
testcase_49 AC 3 ms
5,248 KB
testcase_50 AC 2 ms
5,248 KB
testcase_51 AC 2 ms
5,248 KB
testcase_52 AC 8 ms
5,248 KB
testcase_53 AC 5 ms
5,248 KB
testcase_54 AC 7 ms
5,248 KB
testcase_55 AC 8 ms
5,248 KB
testcase_56 AC 8 ms
5,248 KB
testcase_57 AC 78 ms
5,248 KB
testcase_58 AC 78 ms
5,248 KB
testcase_59 AC 77 ms
5,248 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#line 2 ".lib/template.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <tuple>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <cmath>
#include <functional>
#include <cassert>
#include <climits>
#include <iomanip>
#include <numeric>
#include <memory>
#include <random>
#define all(obj) (obj).begin(), (obj).end()
#define range(i, l, r) for(int i=l;i<r;i++)
#define bit_subset(i, S) for(int i=S, zero_cnt=0;(zero_cnt+=i==S)<2;i=(i-1)&S)
#define bit_kpop(i, n, k) for(int i=(1<<k)-1,x_bit,y_bit;i<(1<<n);x_bit=(i&-i),y_bit=i+x_bit,i=(!i?(1<<n):((i&~y_bit)/x_bit>>1)|y_bit))
#define bit_kth(i, k) ((i >> k)&1)
#define bit_highest(i) (i?63-__builtin_clzll(i):-1)
#define bit_lowest(i) (i?__builtin_ctzll(i):-1)
using ll = long long;
using ld = long double;
using ul = uint64_t;
using pi = std::pair<int, int>;
using pl = std::pair<ll, ll>;
template<typename T>
using vec = std::vector<T>;
using namespace std;

template<typename F, typename S>
std::ostream &operator<<(std::ostream &dest, const std::pair<F, S> &p){
  dest << p.first << ' ' << p.second;
  return dest;
}
template<typename T>
std::ostream &operator<<(std::ostream &dest, const std::vector<std::vector<T>> &v){
  int sz = v.size();
  if(sz==0) return dest;
  for(int i=0;i<sz;i++){
    int m = v[i].size();
    for(int j=0;j<m;j++) dest << v[i][j] << (i!=sz-1&&j==m-1?'\n':' ');
  }
  return dest;
}
template<typename T>
std::ostream &operator<<(std::ostream &dest, const std::vector<T> &v){
  int sz = v.size();
  if(sz==0) return dest;
  for(int i=0;i<sz-1;i++) dest << v[i] << ' ';
  dest << v[sz-1];
  return dest;
}
template<typename T, size_t sz>
std::ostream &operator<<(std::ostream &dest, const std::array<T, sz> &v){
  if(sz==0) return dest;
  for(int i=0;i<sz-1;i++) dest << v[i] << ' ';
  dest << v[sz-1];
  return dest;
}
template<typename T>
std::ostream &operator<<(std::ostream &dest, const std::set<T> &v){
  for(auto itr=v.begin();itr!=v.end();){
    dest << *itr;
    itr++;
    if(itr!=v.end()) dest << ' ';
  }
  return dest;
}
template<typename T, typename E>
std::ostream &operator<<(std::ostream &dest, const std::map<T, E> &v){
  for(auto itr=v.begin();itr!=v.end();){
    dest << '(' << itr->first << ", " << itr->second << ')';
    itr++;
    if(itr!=v.end()) dest << '\n';
  }
  return dest;
}
template<typename T>
vector<T> make_vec(size_t sz, T val){return std::vector<T>(sz, val);}
template<typename T, typename... Tail>
auto make_vec(size_t sz, Tail ...tail){
  return std::vector<decltype(make_vec<T>(tail...))>(sz, make_vec<T>(tail...));
}
template<typename T>
vector<T> read_vec(size_t sz){
  std::vector<T> v(sz);
  for(int i=0;i<sz;i++) std::cin >> v[i];
  return v;
}
template<typename T, typename... Tail>
auto read_vec(size_t sz, Tail ...tail){
  auto v = std::vector<decltype(read_vec<T>(tail...))>(sz);
  for(int i=0;i<sz;i++) v[i] = read_vec<T>(tail...);
  return v;
}

void io_init(){
  std::cin.tie(nullptr);
  std::ios::sync_with_stdio(false);
}
#line 2 ".lib/graph/edge.hpp"

template<typename edge_weight>
struct edge_base{
  using weight = edge_weight;
  int to();
  int from();
  int id();
  weight wei();
  static weight z();
  edge_base<weight> reverse();
};

template<typename edge_weight>
struct simple_edge: edge_base<edge_weight>{
  using weight = edge_weight;
  int s, t;
  simple_edge(): s(-1), t(-1){}
  simple_edge(int a, int b): s(a), t(b){}
  int to(){return t;}
  int from(){return s;}
  int id(){return -1;}
  weight wei(){return 1;}
  static weight z(){return 0;}
  simple_edge<weight> reverse(){return simple_edge<weight>{t, s};}
};

template<typename edge_weight>
struct weighted_edge: edge_base<edge_weight>{
  using weight = edge_weight;
  int s, t;
  weight w;
  weighted_edge(): s(-1), t(-1), w(0){}
  weighted_edge(int a, int b, weight c): s(a), t(b), w(c){}
  int to(){return t;}
  int from(){return s;}
  int id(){return -1;}
  weight wei(){return w;}
  static weight z(){return 0;}
  weighted_edge<weight> reverse(){return weighted_edge<weight>{t, s, w};}
};

template<typename edge_weight>
struct labeled_edge: edge_base<edge_weight>{
  using weight = edge_weight;
  int s, t, i;
  labeled_edge(): s(-1), t(-1), i(-1){}
  labeled_edge(int a, int b, int i): s(a), t(b), i(i){}
  int to(){return t;}
  int from(){return s;}
  int id(){return i;}
  weight wei(){return 1;}
  static weight z(){return 0;}
  labeled_edge<weight> reverse(){return labeled_edge<weight>{t, s, i};}
};

template<typename edge_weight>
struct weighted_labeled_edge: edge_base<edge_weight>{
  using weight = edge_weight;
  int s, t, i;
  weight w;
  weighted_labeled_edge(): s(-1), t(-1), i(-1), w(0){}
  weighted_labeled_edge(int a, int b, weight w, int i): s(a), t(b), w(w), i(i){}
  int to(){return t;}
  int from(){return s;}
  int id(){return i;}
  weight wei(){return w;}
  static weight z(){return 0;}
  weighted_labeled_edge<weight> reverse(){return weighted_labeled_edge<weight>{t, s, w, i};}
};
#line 3 ".lib/graph/tree_algorithm.hpp"

// !
template<typename edge>
void tree_diameter_dfs(int cur, int par, typename edge::weight d, typename edge::weight &dmax, int &vmax, const vec<vec<edge>> &g){
  if(d > dmax) dmax = d, vmax = cur;
  for(edge &e : g[cur]){
    if(e.to() == par) continue;
    tree_diameter_dfs(e.to(), cur, d + e.wei(), dmax, vmax);
  }
}
// {直径, s, t}
template<typename edge>
std::tuple<typename edge::weight, int, int> tree_diameter(const vec<vec<edge>> &g){
  int s = 0, t = 0;
  typename edge::weight d = edge::z();
  tree_diameter_dfs(s, -1, 0, d, t, g);
  s = t, t = 0, d = edge::z();
  tree_diameter_dfs(s, -1, 0, d, t, g);
  return {d, s, t};
}
template<typename edge>
std::tuple<vec<vec<int>>, vec<int>, vec<int>, vec<int>> centroid_decomposition_build(const vec<vec<edge>> &g){
  int n = g.size();
  assert(n);
  vec<vec<int>> G(n);
  std::vector<int> size_i(n, 0), dep_i(n, std::numeric_limits<int>::max()), par_i(n, -1);

  auto add_edge = [&](int p, int c)->void{
    G[p].push_back(c);
    G[c].push_back(p);
    par_i[c] = p;
  };
  auto find_centroid = [&](auto &&find_centroid, int v, int p, const int N, const int8_t rank)->std::pair<int, int>{
    int sz = 1;
    for(edge &e: g[v]){
      if(e.t == p || dep_i[e.t] < rank) continue;
      auto [sz_c, cent_c] = find_centroid(find_centroid, e.t, v, N, rank);
      if(sz_c == -1) return {-1, cent_c};
      size_i[e.t] = sz_c, sz += sz_c;
    }
    //サイズが半分以上になったとき
    if(sz * 2 >= N){
      size_i[v] = N;
      dep_i[v] = rank;
      for(edge &e: g[v]){
        if(e.t == p || dep_i[e.t] < rank) continue;
        auto [sz_c, cent_c] = find_centroid(find_centroid, e.t, -1, size_i[e.t], rank + 1);
        assert(sz_c == -1);
        add_edge(v, cent_c);
      }
      if(p != -1){
        auto [sz_c, cent_c] = find_centroid(find_centroid, p, -1, N - sz, rank + 1);
        assert(sz_c == -1);
        add_edge(v, cent_c);
      }
      return {-1, v};// 重心を発見
    }
    return {sz, -1};
  };
  find_centroid(find_centroid, 0, -1, n, 0);
  return {G, size_i, dep_i, par_i};
}
template<typename edge>
struct hld{
  vec<int> subsize, depth, parent, in, out, head, rev;
  hld(vec<vec<edge>> &g, int root){
    build(g, root);
  }
  void dfs_sz(int cur, int par, int dep, vec<vec<edge>> &g){
    depth[cur] = dep;
    parent[cur] = par;
    subsize[cur] = 1;
    if(g[cur].size() && g[cur][0].to() == par) std::swap(g[cur][0], g[cur].back());
    for(int i = 0; i < g[cur].size(); i++){
      edge &e = g[cur][i];
      if(e.to() == par) continue;
      dfs_sz(e.to(), cur, dep + 1, g);
      subsize[cur] += subsize[e.to()];
      if(subsize[g[cur][0].to()] < subsize[e.to()]) std::swap(g[cur][0], e);
    }
  }
  void dfs_hld(int cur, int par, int &times, vec<vec<edge>> &g){
    in[cur] = times++;
    rev[in[cur]] = cur;
    for(edge &e : g[cur]){
      if(e.to() == par) continue;
      head[e.to()] = (g[cur][0].to() == e.to() ? head[cur] : e.to());
      dfs_hld(e.to(), cur, times, g);
    }
    out[cur] = times;
  }
  void build(vec<vec<edge>> &g, int root){
    int n = g.size();
    subsize.resize(n), depth.resize(n), parent.resize(n);
    in.resize(n), out.resize(n), head.resize(n), rev.resize(n);
    dfs_sz(root, -1, 0, g);
    int t = 0;
    dfs_hld(root, -1, t, g);
  }
  int la(int v, int k){
    if(depth[v] < k) return -1;
    while(true){
      int u = head[v];
      if(in[v] - k >= in[u]) return rev[in[v] - k];
      k -= in[v] - in[u] + 1;
      v = parent[u];
    }
  }
  int lca(int u, int v){
    for(;; v = parent[head[v]]){
      if(in[u] > in[v]) std::swap(u, v);
      if(head[u] == head[v]) return u;
    }
  }
  bool is_ancestor(int u, int v){
    if(depth[u] > depth[v]) std::swap(u, v);
    return u == la(v, depth[v] - depth[u]);
  }
  int kth_vertex_on_path(int u, int v, int k){
    int l = lca(u, v), dlu = depth[u] - depth[l];
    if(dlu > k) return la(u, k);
    k = depth[v] - depth[l] - k + dlu;
    if(k < 0) return -1;
    return la(v, k);
  }
  // hldに基づいて頂点を[0, n), 辺を[1, n)に並び替えた時に, 任意のパスはO(log(n))個の区間になる

  // 頂点[0, n)の中でuの位置
  int index_vertex(int u){
    return in[u];
  }
  // 辺[1, n)の中でe{s, t}の位置, 辺が存在しない場合は-1
  int index_edge(int s, int t){
    if(in[s] > in[t]) std::swap(s, t);
    if(parent[t] != s) return -1;
    return in[s] + 1;
  }
  using path = vec<std::pair<int, int>>;
  // 順序を気にせずO(log(n))個の区間を列挙
  path unordered_path(int u, int v, bool is_edge = false){
    path res;
    for(;; v = parent[head[v]]){
      if(in[u] > in[v]) std::swap(u, v);
      if(head[u] == head[v]) break;
      res.push_back({in[head[v]], in[v] + 1});
    }
    res.push_back({in[u] + is_edge, in[v] + 1});
    return res;
  }
  // {lca->uのパス, lca->vのパス}
  std::pair<path, path> ordered_path(int u, int v, bool is_edge = false){
    bool is_swaped = false;
    std::pair<path, path> res;
    path &a = res.first, &b = res.second;
    for(;; v = parent[head[v]]){
      if(in[u] > in[v]) std::swap(u, v), std::swap(a, b), is_swaped ^= 1;
      if(head[u] == head[v]) break;
      b.push_back({in[head[v]], in[v] + 1});
    }
    b.push_back({in[u] + is_edge, in[v] + 1});
    if(is_swaped) std::swap(a, b);
    std::reverse(a.begin(), a.end());
    std::reverse(b.begin(), b.end());
    return {a, b};
  }
};
// !
// 部分木のサイズ, 深さ, 親
template<typename edge>
std::tuple<vec<int>, vec<int>, vec<int>> simple_dfs(const vec<vec<edge>> &g, int root){
  int n = g.size();
  vec<int> sz(n, 1), de(n), pa(n);
  auto simple_dfs_f = [&](auto simple_dfs_f, int cur, int par, int dep)->void{
    pa[cur] = par;
    de[cur] = dep;
    for(edge &e : g[cur]){
      if(e.to() == par) continue;
      simple_dfs_f(simple_dfs_f, e.to(), cur, dep + 1);
      sz[cur] += sz[e.to()];
    }
  };
  simple_dfs_f(simple_dfs_f, root, -1, 0);
  return {sz, de, pa};
}

// !
// pre_order 頂点を初めて訪れた時刻を記録
// in_pre: 初めて訪れた時刻
// out_pre: in_pre以降に初めてvより上のノードが現れる時刻, 区間[in_pre, out_pre)は部分木
// rev_pre: in_preの順番に頂点を並び替えた状態
template<typename edge>
struct dfs_order{
  vec<int> subsize, depth, parent;
  vec<int> in_pre, out_pre, rev_pre;// 訪れた順番(サイズN)
  vec<int> in_path, out_path, rev_path;// 戻る辺も考慮する(サイズ2N-1)
  dfs_order(vec<vec<edge>> &g, int root){
    build(g, root);
  }
  void dfs_build_inner(int cur, int par, int dep, int &tpath, int &tpre, vec<vec<edge>> &g){
    depth[cur] = dep;
    parent[cur] = par;
    in_path[cur] = tpath;
    rev_path[tpath++] = cur;
    in_pre[cur] = out_path[cur] = tpre;
    rev_pre[tpre++] = cur;
    for(int i = 0; i < g[cur].size(); i++){
      int to = g[cur][i].to();
      if(to == par) continue;
      dfs_build_inner(to, cur, dep + 1, tpath, tpre, g);
      subsize[cur] += subsize[to];
      out_path[cur] = tpath;
      rev_path[tpath++] = cur;
    }
    out_pre[cur] = tpre;
  }
  void build(vec<vec<edge>> &g, int root){
    int n = g.size();
    depth.resize(n), parent.resize(n), subsize.resize(n, 1);
    in_pre.resize(n), out_pre.resize(n), rev_pre.resize(n);
    in_path.resize(n), out_path.resize(n), rev_path.resize(2 * n - 1);
    int a = 0, b = 0;
    dfs_build_inner(root, -1, 0, a, b, g);
  }
  // vがuの部分木に含まれるか(u自身も部分木)
  bool is_subtree(int u, int v){
    return in_path[u] <= in_path[v] && out_path[v] <= out_path[u];
  }
  // u->vパス(最短経路)にwが含まれるか(端点も含む)
  // vがuの部分木 -> wがuの部分木 && vがwの部分木
  // それ以外 -> wがuかvのどちらかを部分木として含む
  bool is_contained_path(int u, int v, int w){
    if(in_path[u] > in_path[v]) std::swap(u, v);
    if(is_subtree(u, v)) return in_path[u] <= in_path[w] && is_subtree(w, v);
    return is_subtree(w, u) || is_subtree(w, v);
  }
  // [in_pre, out_pre)がuの部分木中に存在する頂点番号
  std::pair<int, int> subtree(int u){
    return {in_pre[u], out_pre[u]};
  }
  /*
  std::pair<int, int> path(){

  }
  */
};

// !
template<typename edge>
struct bfs_order{
  vec<int> parent;
  vec<int> in_bfs, rev_bfs, child_in;
  vec<vec<edge>> &g;
  bfs_order(vec<vec<edge>> &g, int root):g(g){
    build(root);
  }
  // 注: g[v][親]が末尾にswapされる
  void build(int root){
    int n = g.size();
    in_bfs.resize(n);
    rev_bfs.resize(n);
    child_in.resize(n, -1);
    parent.resize(n);
    std::queue<std::pair<int, int>> q;
    q.push({root, -1});
    int t = 0;
    while(!q.empty()){
      auto [v, p] = q.front();
      q.pop();
      parent[v] = p;
      if(child_in[p] == -1) child_in[p] = t;
      rev_bfs[t] = v;
      in_bfs[v] = t++;
      for(int i = 0; i < g[v].size(); i++){
        if(g[v][i].to() == p) std::swap(g[v][i], g[v].back());
        q.push({g[v][i].to(), v});
      }
    }
  }
  // vがuの何番目の子か(0-indexed), 親でない場合-1
  int child_index_find(int u, int v){
    if(parent[v] != u) return -1;
    return in_bfs[v] - child_in[u];
  }
  // e{u, v}を探す
  edge get_edge(int u, int v){
    return g[u][child_index_find(u, v)];
  }
  edge get_parent_edge(int u){
    /*
    // 辺が親->子片方向だと壊れる
    return g[u].back();
    */
    int p = parent[u];
    return g[p][child_index_find(p, u)];
  }
};

template<int (*lca)(int, int), int (*dfs_in)(int), int (*dep)(int)>
std::pair<vec<int>, vec<std::pair<int, int>>> lca_tree_build(vec<int> v){
  if(v.empty()) return {};
  std::sort(v.begin(), v.end(), [&](int a, int b){return dfs_in(a) < dfs_in(b);});
  v.erase(std::unique(v.begin(), v.end()), v.end());
  std::stack<int> st;
  vec<std::pair<int, int>> E;
  vec<int> V;
  st.push(v[0]);
  for(int i = 1; i < v.size(); i++){
    if(v[i] == v[i - 1]) continue;
    int l = lca(v[i], v[i - 1]);
    while(true){
      int c = st.top();
      st.pop();
      if(st.empty() || dep(st.top()) <= dep(l)){
        st.push(l);
        st.push(v[i]);
        if(dep(c) > dep(l)){
          E.push_back({l, c});
          V.push_back(c);
          V.push_back(l);
        }
        break;
      }
      int p = st.top();
      if(dep(c) > dep(p)){
        E.push_back({p, c});
        V.push_back(c), V.push_back(p);
      }
    }
  }
  while(st.size() >= 2){
    int c = st.top();
    st.pop();
    int p = st.top();
    if(c != p) E.push_back({p, c}), V.push_back(c), V.push_back(p);
  }
  if(!st.empty()) V.push_back(st.top());
  std::sort(V.begin(), V.end());
  V.erase(std::unique(V.begin(), V.end()), V.end());
  return {V, E};
}
#line 5 ".lib/graph/tree.hpp"

template<typename edge>
struct tree{
  using weight = typename edge::weight;
  template<typename T>
  using vec = std::vector<T>;
  using graph = vec<vec<edge>>;
  using simple_tree = tree<simple_edge<int>>;
public:
  graph g;
  int n, r;
  vec<int> subsize, depth, parent;
  hld<edge> *hld_p;
  dfs_order<edge> *dfs_p;
  bfs_order<edge> *bfs_p;
  tree(int n, int r = 0): g(n), n(n), r(r), hld_p(nullptr), dfs_p(nullptr), bfs_p(nullptr){}
  tree(graph &g, int r = 0): g(g), n(g.size()), r(r), hld_p(nullptr), dfs_p(nullptr), bfs_p(nullptr){}

  void add_edge(int a, edge e){
    assert(0 <= a && a < n);
    g[a].push_back(e);
  }
  void add_dual(int a, int b, edge e){
    assert(0 <= a && a < n);
    g[a].push_back(e);
    g[b].push_back(e.reverse());
  }
  void simple_dfs(){
    auto [s, d, p] = simple_dfs(g, r);
    subsize = s, depth = d, parent = p;
  }
  void hld_build(){
    hld_p = new hld<edge>(g, r);
    subsize = hld_p->subsize, depth = hld_p->depth, parent = hld_p->parent;
  }
  void dfs_build(){
    dfs_p = new dfs_order(g, r);
    subsize = dfs_p->subsize, depth = dfs_p->depth, parent = dfs_p->parent;
  }
  void bfs_build(){
    bfs_p = new bfs_order(g, r);
    parent = bfs_p->parent;
  }
  int lca(int u, int v){
    return hld_p->lca(u, v);
  }
  int la(int u, int k){
    return hld_p->la(u, k);
  }
  int dep(int v){
    return depth[v];
  }
  int par(int v){
    return parent[v];
  }
  int size(int v){
    return subsize[v];
  }
  std::pair<vec<int>, vec<std::pair<int, int>>> lca_tree(vec<int> v){
    static std::function<int(int, int)> dfs_in = [&](int v){return dfs_p->in_pre[v];};
    return lca_tree_build<lca, dfs_in, dep>(v);
  }
  // vがuの何番目の子か(0-indexed), 親でない場合-1
  int child_index_find(int u, int v){
    return bfs_p->child_index_find(u, v);
  }
  // s->tパスの辺
  vec<edge> get_path(int s, int t){
    int l = lca(s, t);
    vec<edge> L, R;
    while(s != l){
      L.push_back(g[s].back());
      s = parent[s];
    }
    while(t != l){
      int p = parent[l];
      R.push_back(g[p][child_index_find(p, l)]);
      l = p;
    }
    std::reverse(R.begin(), R.end());
    L.insert(L.end(), R.begin(), R.end());
    return L;
  }
  // vがuの部分木に含まれるか(u自身も部分木)
  bool is_subtree(int u, int v){
    return dfs_p->is_subtree(u, v);
  }
  // u->vパス(最短経路)にwが含まれるか(端点も含む)
  // vがuの部分木 -> wがuの部分木 && vがwの部分木
  // それ以外 -> wがuかvのどちらかを部分木として含む
  bool is_contained_path(int u, int v, int w){
    return dfs_p->is_contained_path(u, v, w);
  }
  simple_tree centroid_decomposition(){
    auto [G, root, size_i, par_i, dep_i] = centroid_decomposition_build<edge>(g);
    simple_tree res(G, root);
    res.subsize = size_i;
    res.parent = par_i;
    res.depth = dep_i;
    return res;
  }
  vec<edge> &operator [](int i){return g[i];}
};
using simple_tree = tree<simple_edge<int>>;
#line 5 ".lib/graph/graph_algorithm.hpp"

// i-bit目が1 -> 頂点iを使う
long long maximum_independent_set(const vec<long long> &g2, long long rem){
  int n = g2.size();
  if(rem == -1) rem = (1LL << n) - 1;
  long long ret = 0;
  int k = -1, m = -1;
  while(true){
    bool update = false;
    for(int i = 0; i < n; i++){
      if(!((rem >> i) & 1)) continue;
      int s = __builtin_popcountll(rem & g2[i]); //次数
      if(s > m) k = i, m = s;
      if(s <= 1){
        rem &= ~(g2[i] | (1LL << i));
        ret |= (1LL << i), update = true;
      }
    }
    if(!update) break;
    k = -1, m = -1;
  }
  if(rem > 0){
    rem &= ~(1LL << k);
    long long p = maximum_independent_set(g2, rem); //kを使わない
    long long q = maximum_independent_set(g2, rem & ~g2[k]); //kを使う
    if(__builtin_popcountll(p) > __builtin_popcountll(q)) ret |= p;
    else ret |= ((1LL << k) | q);
  }
  return ret;
}

// プリム法, 連結なら始点sは関係ない
template<typename edge>
vec<edge> undirected_mst(vec<vec<edge>> &g, int s = 0){
  int n = g.size();
  assert(s < n);
  static vec<bool> V(n, 0);
  vec<edge> res;
  using pde = pair<typename edge::weight, edge>;
  std::priority_queue<pde, vec<pde>, std::function<bool(pde, pde)>> que([](pde a, pde b){
    return a.first > b.first;
  });
  V[s] = true;
  for(edge &e : g[s]) que.push(pde{e.wei(), e});
  while(!que.empty()){
    auto [d, e] = que.top();
    que.pop();
    if(V[e.to()]) continue;
    V[e.to()] = true;
    res.push_back(e);
    for(edge &ec : g[e.to()]) if(!V[ec.to()]) que.push({ec.wei(), ec});
  }
  for(edge &e : res) V[e.to()] = V[e.from()] = false;
  return res;
}
// !
// プリム法
template<typename edge>
vec<vec<edge>> undirected_mst_forest(vec<vec<edge>> &g){
  int n = g.size();
  static vec<bool> V(n, 0);
  vec<vec<edge>> res;
  using pde = pair<typename edge::weight, edge>;
  std::priority_queue<pde, vec<pde>, std::function<bool(pde, pde)>> que([](pde a, pde b){
    return a.first > b.first;
  });
  for(int i = 0; i < n; i++){
    if(V[i]) continue;
    V[i] = true;
    res.push_back(vec<edge>());
    for(edge &e : g[i]) que.push(pde{e.wei(), e});
    while(!que.empty()){
      auto [d, e] = que.top();
      que.pop();
      if(V[e.to()]) continue;
      V[e.to()] = true;
      res.push_back(e);
      for(edge &ec : g[e.to()]) if(!V[ec.to()]) que.push({ec.wei(), ec});
    }
    for(edge &e : res.back()) V[e.to()] = V[e.from()] = false;
  }
  return res;
}

// !
// 終了時にinが0でない要素がある -> 閉路が存在する
template<typename edge>
vec<int> topological_sort(vec<vec<edge>> &g){
  int n = g.size();
  std::queue<int> que;
  vec<int> in(n, 0), res;
  for(int i = 0; i < n; i++) for(edge e : g[i]) in[e.to()]++;
  for(int i = 0; i < n; i++) if(!in[i]) que.push(i);
  while(!que.empty()){
    int p = que.front();
    que.pop();
    res.push_back(p);
    for(edge &e : g[p]){
      int to = e.to();
      if(!(--in[to])) que.push(to);
    }
  }
  return res;
}

template<typename edge>
pair<vec<int>, vec<vec<int>>> scc(vec<vec<edge>> &g){
  int n = g.size();
  vec<int> v(n), cmp(n, 0);
  vec<vec<int>> rg(n), V;
  auto scc_dfs = [&](auto &&scc_dfs, int cur, int &sz)->void{
    cmp[cur] = -1;
    for(edge &e : g[cur]){
      int to = e.to();
      rg[to].push_back(cur);
      if(cmp[to] == 0) scc_dfs(scc_dfs, to, sz);
    }
    v[sz++] = cur;
  };
  auto scc_rdfs = [&](auto &&scc_rdfs, int cur, const int k)->void{
    cmp[cur] = k;
    V[k].push_back(cur);
    for(int to : rg[cur]) if(cmp[to] == -1) scc_rdfs(scc_rdfs, to, k);
  };
  for(int i = 0, j = 0; i < n; i++) if(!cmp[i]) scc_dfs(scc_dfs, i, j);
  for(int i = (int)v.size() - 1, j = 0; i >= 0; i--){
    if(cmp[v[i]] == -1){
      V.push_back(vec<int>());
      scc_rdfs(scc_rdfs, v[i], j++);
    }
  }
  return {cmp, V};
}


template<typename edge>
pair<vec<int>, vec<vec<int>>> two_edge_connected(vec<vec<edge>> &g){
  int n = g.size();
  vec<int> v(n), cmp(n, 0);
  vec<vec<int>> V;
  vec<vec<bool>> edge_used(n);
  auto tec_dfs = [&](auto &&tec_dfs, int cur, int &sz)->void{
    cmp[cur] = -1;
    for(int i = 0; i < g[cur].size(); i++){
      int to = g[cur][i].to();
      if(cmp[to] == 0) edge_used[cur][i] = true, tec_dfs(tec_dfs, to, sz);
    }
    v[sz++] = cur;
  };
  auto tec_rdfs = [&](auto &&tec_rdfs, int cur, const int k)->void{
    cmp[cur] = k;
    V[k].push_back(cur);
    for(int i = 0; i < g[cur].size(); i++){
      int to = g[cur][i].to();
      if(cmp[to] == -1 && !edge_used[cur][i]) tec_rdfs(tec_rdfs, to, k);
    }
  };
  for(int i = 0; i < n; i++) edge_used[i].resize(g[i].size(), 0);
  for(int i = 0, j = 0; i < n; i++) if(!cmp[i]) tec_dfs(tec_dfs, i, j);
  for(int i = (int)v.size() - 1, j = 0; i >= 0; i--){
    if(cmp[v[i]] == -1){
      V.push_back(vec<int>());
      tec_rdfs(tec_rdfs, v[i], j++);
    }
  }
  return {cmp, V};
}

// 二重頂点連結成分分解
template<typename edge>
pair<vec<int>, vec<vec<int>>> bcc(vec<vec<edge>> &g){
  int n = g.size();
  vec<vec<int>> V;
  vec<int> child(n, 0), dep(n, -1), low(n);
  vec<bool> used(n, false), is_articulation(n, false);
  vec<edge> tmp_edge;

  auto bcc_dfs = [&](auto &&bcc_dfs, int cur, int par, int d)->void{
    if(par != -1) child[par]++;
    dep[cur] = low[cur] = d;
    for(edge &e : g[cur]){
      int to = e.to();
      if(to == par) continue;
      if(dep[to] < dep[cur]) tmp_edge.push_back(e);
      if(dep[e.to()] == -1){
        bcc_dfs(bcc_dfs, to, cur, d + 1);
        if(low[to] >= dep[cur]){
          is_articulation[cur] = true;
          V.push_back(vec<int>());
          bool is_ok = false;
          while(!tmp_edge.empty() && !is_ok){
            edge e = tmp_edge.back();
            tmp_edge.pop_back();
            if(e.from() == cur && e.to() == to) is_ok = true;
            if(!used[e.to()]) V.back().push_back(e.to()), used[e.to()] = true;
            if(!used[e.from()]) V.back().push_back(e.from()), used[e.from()] = true;
          }
          for(int v : V.back()) used[v] = false;
        }
        low[cur] = std::min(low[cur], low[to]);
      }else low[cur] = std::min(low[cur], dep[to]);
    }
  };
  for(int i = 0; i < n; i++){
    if(dep[i] != -1) continue;
    int vsz_pre = V.size();
    bcc_dfs(bcc_dfs, i, -1, 0);
    is_articulation[i] = (child[i] > 1);
    if(V.size() == vsz_pre) V.push_back(vec<int>{i});// 孤立点
  }
  return {child, V};
}

// !
// g[i]の辺を{同じcmpへの辺, 異なるcmpへの辺}に並び替える, O(V + E)
template<typename edge>
void cmp_edge_arrange(const vec<int> &cmp, vec<vec<edge>> &g){
  int n = g.size();
  for(int i = 0; i < n; i++){
    int m = g[i].size();
    int l = 0, r = m - 1;
    while(l < r){
      while(l < m && cmp[i] == cmp[g[i][l].to()]) l++;
      while(0 < r && cmp[i] == cmp[g[i][r].to()]) r--;
      if(l < r) std::swap(g[i][l], g[i][r]);
    }
  }
}

// !
// rを根とするbfs木, 重みを気にしない O(V + E)
template<typename edge>
tree<edge> bfs_tree(vec<vec<edge>> &g, int r){
  int n = g.size();
  std::queue<int> que;
  vec<bool> used(n, false);
  que.push(r);
  tree<edge> res(n, r);
  used[r] = true;
  while(!que.empty()){
    int v = que.front();
    que.pop();
    for(edge &e : g[v]){
      int to = e.to();
      if(used[to]) continue;
      used[to] = true;
      res.add_edge(v, e);
      que.push(to);
    }
  }
  return res;
}

// !
// rを根とするbfs木, 最短経路的 O((V + E)logV)
// {木, 重みのテーブル}
template<typename edge>
std::pair<tree<edge>, vec<typename edge::weight>> bfs_tree_shortest(vec<vec<edge>> &g, int r){
  int n = g.size();
  using weight = typename edge::weight;
  using pdv = std::pair<weight, int>;
  static constexpr weight inf = std::numeric_limits<weight>::max() / 2;
  std::priority_queue<pdv, vec<pdv>, std::greater<pdv>> que;
  vec<weight> dist(n, inf);
  dist[r] = edge::z();
  que.push({edge::z(), r});
  tree<edge> res(n, r);
  while(!que.empty()){
    auto [d, v] = que.top();
    que.pop();
    if(dist[v] < d) continue;
    for(edge &e : g[v]){
      int to = e.to();
      weight nxtd = d + e.wei();
      if(dist[to] > nxtd){
        dist[to] = nxtd;
        res.add_edge(v, e);
        que.push({nxtd, to});
      }
    }
  }
  return {res, dist};
}

// O((V + E)logV)
// 辺の重みが非負
template<typename edge>
struct dijkstra{
private:
  using weight = typename edge::weight;
  using dist_p = pair<weight, int>;
  vec<vec<edge>> &g;
public:
  dijkstra(vec<vec<edge>> &g): g(g){}
  static constexpr weight inf = std::numeric_limits<weight>::max() / 2;
  static constexpr weight minf = std::numeric_limits<weight>::min() / 2;
  vec<weight> dist;
  vec<edge> par;
  void build(int s){
    int n = g.size();
    if(dist.empty()){
      dist.resize(n, inf);
      par.resize(n, edge{});
    }else{
      std::fill(dist.begin(), dist.end(), inf);
      std::fill(par.begin(), par.end(), edge{});
    }
    std::priority_queue<dist_p, vec<dist_p>, std::greater<dist_p>> que;
    dist[s] = edge::z();
    que.push(dist_p(edge::z(), s));
    while(!que.empty()){
      auto [w, v] = que.top();
      que.pop();
      if(dist[v] < w) continue;
      for(edge &e: g[v]){
        weight d = dist[v] + e.wei();
        int to = e.to();
        if(dist[to] > d){
          dist[to] = d;
          par[to] = e;
          que.push(dist_p(d, to));
        }
      }
    }
  }
  vec<edge> get_path(int v){
    assert(!dist.empty());
    vec<edge> res;
    while(par[v].from() != -1) res.push_back(par[v]), v = par[v].from();
    std::reverse(res.begin(), res.end());
    return res;
  }
  weight operator [](int v){return dist[v];}
};

// O(VE)
// inf: 到達不可, minf: 負の閉路
template<typename edge>
struct bellman_ford{
private:
  using weight = typename edge::weight;
  using dist_p = pair<weight, int>;
  vec<vec<edge>> &g;
public:
  bellman_ford(vec<vec<edge>> &g): g(g){}
  static constexpr weight inf = std::numeric_limits<weight>::max() / 2;
  static constexpr weight minf = std::numeric_limits<weight>::min() / 2;
  vec<weight> dist;
  vec<edge> par;

  void build(int s){
    int n = g.size();
    if(dist.empty()){
      dist.resize(n, inf);
      par.resize(n);
    }else{
      std::fill(dist.begin(), dist.end(), inf);
      std::fill(par.begin(), par.end(), edge{});
    }
    dist[s] = edge::z();
    for(int lp = 0; ; lp++){
      bool update = false;
      for(int i = 0; i < n; i++){
        if(dist[i] == inf) continue;
        for(edge e : g[i]){
          weight &dto = dist[e.to()];
          if(dto == minf){
            if(dto != minf) update = true;
            dto = minf;
          }else if(dto == inf || dto > dist[i] + e.wei()){
            dto = (lp > n ? minf : dist[i] + e.wei());
            par[e.to()] = e;
            update = true;
          }
        }
      }
      if(!update) break;
    }
  }
  vec<edge> get_path(int v){
    assert(!dist.empty());
    vec<edge> res;
    while(par[v].from() != -1) res.push_back(par[v]), v = par[v].from();
    std::reverse(res.begin(), res.end());
    return res;
  }
  weight operator [](int v){return dist[v];}
};

// O(V^3)
template<typename edge>
struct warshall_floyd{
private:
  using weight = typename edge::weight;
  vec<vec<edge>> &g;
public:
  warshall_floyd(vec<vec<edge>> &g): g(g){}
  static constexpr weight inf = std::numeric_limits<weight>::max() / 2;
  static constexpr weight minf = std::numeric_limits<weight>::min() / 2;
  vec<vec<weight>> dist;
  void build(){
    int n = g.size();
    dist.resize(n, vec<weight>(n, inf));
    for(int i = 0; i < n; i++){
      dist[i][i] = 0;
      for(edge &e : g[i]){
        dist[i][e.to()] = std::min(dist[i][e.to()], e.wei());
      }
    }
    for(int k = 0; k < n; k++){
      for(int s = 0; s < n; s++){
        for(int t = 0; t < n; t++){
          dist[s][t] = std::min(dist[s][t], dist[s][k] + dist[k][t]);
        }
      }
    }
  }
  vec<weight>& operator [](int v){return dist[v];}
};
#line 5 ".lib/graph/graph.hpp"

/*
template<typename edge = int, typename dist = int, typename edge_type = simple_edge<edge, dist>>
struct dense_graph{

};
*/
template<typename edge>
struct general_graph{
  using weight = typename edge::weight;
  template<typename T>
  using vec = std::vector<T>;
  using graph = vec<vec<edge>>;
  int n;
  graph g;
  general_graph(int n): n(n), g(n){}

  void add_edge(int a, edge e){
    g[a].push_back(e);
  }

  // i-bit目が1 -> 頂点iを使う
  long long maximum_independent_set(){
    assert(n <= 62);
    vec<long long> g2(n, 0);
    for(int i = 0; i < n; i++) for(edge &e : g[i]) g2[i] |= (1LL << e.to());
    return maximum_independent_set(g2, -1);
  }

  // !
  vec<edge> undirected_mst_build(int s = 0){
    return undirected_mst<edge>(g, s);
  }
  // 終了時にinが0でない要素がある -> 閉路が存在する
  vec<int> topological_sort(){
    return topological_sort(g);
  }
  pair<vec<int>, vec<vec<int>>> scc(){
    return scc(g);
  }
  pair<vec<int>, vec<vec<int>>> two_edge_connected_build(){
    return two_edge_connected<edge>(g);
  }
  pair<vec<int>, vec<vec<int>>> bcc_build(){
    return bcc<edge>(g);
  }
  // g[i]の辺を{同じcmpへの辺, 異なるcmpへの辺}に並び替える, O(V + E)
  void cmp_edge_arrange(const vec<int> &cmp){
    cmp_edge_arrange(cmp, g);
  }
  // rを根とするbfs木, 重みを気にしない O(V + E)
  tree<edge> bfs_tree(int r){
    return bfs_tree(g, r);
  }
  // rを根とするbfs木, 最短経路的 O((V + E)logV)
  tree<edge> bfs_tree_shortest(int r){
    return bfs_tree_shortest(g, r);
  }
  dijkstra<edge> dijkstra_build(){
    return dijkstra<edge>(g);
  }
  bellman_ford<edge> bellman_ford_build(){
    return bellman_ford<edge>(g);
  }
  warshall_floyd<edge> warshall_floyd_build(){
    return warshall_floyd<edge>(g);
  }

  // O(E)
  // 任意のサイクル bfs木 -> e{s, t}を min(dep[s], dep[t])の昇順に確かめる
  // iを含む任意のサイクル bfs木 -> e{s, t}s, tのいずれかがiの部分木かつlca(s, t)がiより上
  //
  /*
  vec<edge> undirected_cycle(const vec<int> &cmp, int s = 0){
    static vec<bool> order(n, -1);
    vec<edge> res;
  }
  */
};

using simple_graph = general_graph<simple_edge<int>>;
template<typename T>
using weighted_graph = general_graph<weighted_edge<T>>;
template<typename T>
using labeled_graph =  general_graph<labeled_edge<T>>;
template<typename T>
using weighted_labeled_graph =  general_graph<weighted_labeled_edge<T>>;
#line 4 ".lib/data_structure/segment_tree/monoid.hpp"

struct point_min_range_min{
  template<typename T>
  static T id(){
    return std::numeric_limits<T>::max();
  }
  template<typename T>
  static T update(T a, T b){
    return std::min(a, b);
  }
  template<typename T>
  static T merge(T a, T b){
    return std::min(a, b);
  }
};

struct point_add_range_min{
  template<typename T>
  static T id(){
    return std::numeric_limits<T>::max();
  }
  template<typename T>
  static T update(T a, T b){
    if(a == id<T>()) return b;
    else if(b == id<T>()) return a;
    return a + b;
  }
  template<typename T>
  static T merge(T a, T b){
    return std::min(a, b);
  }
};

struct point_max_range_max{
  template<typename T>
  static T id(){
    return std::numeric_limits<T>::min();
  }
  template<typename T>
  static T update(T a, T b){
    return std::max(a, b);
  }
  template<typename T>
  static T merge(T a, T b){
    return std::max(a, b);
  }
};

struct point_add_range_max{
  template<typename T>
  static T id(){
    return std::numeric_limits<T>::min();
  }
  template<typename T>
  static T update(T a, T b){
    if(a == id<T>()) return b;
    else if(b == id<T>()) return a;
    return a + b;
  }
  template<typename T>
  static T merge(T a, T b){
    return std::max(a, b);
  }
};

struct point_add_range_sum{
  template<typename T>
  static T id(){
    return 0;
  }
  template<typename T>
  static T update(T a, T b){
    return a + b;
  }
  template<typename T>
  static T merge(T a, T b){
    return a + b;
  }
};

struct point_set_range_composite{
  static constexpr int mod = 998244353;
  template<typename T>
  static T id(){
    return {1, 0, 0};
  }
  template<typename T>
  static T update(T a, T b){
    return b;
  }
  template<typename T>
  static T merge(T a, T b){
    int xy = ((long long)a[0] * b[0]) % mod;
    int ab = ((long long)a[1] * b[0] + b[1]) % mod;
    int ba = ((long long)b[2] * a[0] + a[2]) % mod;
    return {xy, ab, ba};
  }
};

struct range_add_range_sum{
  template<typename T>
  static T id1(){
    return T(0);
  }
  template<typename E>
  static E id2(){
    return E(0);
  }
  template<typename T>
  static T merge(T a, T b){
    return a + b;
  }
  template<typename T, typename E>
  static T apply(T a, E b, int l, int r){
    return a + b * (r - l);
  }
  template<typename E>
  static E propagate(E a, E b){
    return a + b;
  }
};

struct range_add_range_max{
  template<typename T>
  static T id1(){
    return std::numeric_limits<T>::min();
  }
  template<typename E>
  static E id2(){
    return 0;
  }
  template<typename T>
  static T merge(T a, T b){
    return std::max(a, b);
  }
  template<typename T, typename E>
  static T apply(T a, E b, int l, int r){
    if(a == id1<T>()) return b * (r - l);
    return a + b;
  }
  template<typename E>
  static E propagate(E a, E b){
    return a + b;
  }
};

#line 151 ".lib/data_structure/segment_tree/monoid.hpp"
struct range_affine_range_sum{
  const static long long MOD = 998244353;
  template<typename T>
  static T id1(){
    return 0;
  }
  template<typename E>
  static E id2(){
    return E{1, 0};
  }
  template<typename T>
  static T merge(T a, T b){
    return (a + b) % MOD;
  }
  template<typename T, typename E>
  static T apply(T a, E b, int l, int r){
    return (a * b[0] + b[1] * (r - l)) % MOD;
  }
  template<typename E>
  static E propagate(E a, E b){
    return E{(a[0] * b[0]) % MOD, (a[1] * b[0] + b[1]) % MOD};
  }
};
#line 3 ".lib/math/integer.hpp"
#include <cstdint>
#line 8 ".lib/math/integer.hpp"
#include <limits>
#line 10 ".lib/math/integer.hpp"

// a^k >= xとなる最小のa^k
uint64_t ceil_pow(uint64_t x, uint64_t a){
  assert(a > 1);
  if(x == 0) return 1;
  static uint64_t INF = std::numeric_limits<uint64_t>::max();
  if(a == 2){
    uint64_t ret = uint64_t(1) << (63 - __builtin_clzll(x));
    if(ret == x) return x;
    assert(ret <= (INF >> 1));
    return ret << 1;
  }
  if(a > 10){
    uint64_t ret = 1;
    while(true){
      if(ret > x / a) break;
      ret *= a;
    }
    if(ret == x) return ret;
    assert(ret <= INF / a);
    return ret * a;
  }
  static std::vector<std::vector<uint64_t>> pow_table(11);
  if(pow_table[a].empty()){
    uint64_t tmp = 1;
    pow_table[a].push_back(1);
    while(true){
      if(tmp > INF / a) break;
      pow_table[a].push_back(tmp *= a);
    }
  }
  auto itr = std::lower_bound(pow_table[a].begin(), pow_table[a].end(), x);
  assert(itr != pow_table[a].end());
  return *itr;
}

// 2^k >= xとなる最小の2^k
uint64_t ceil_2_pow(uint64_t x){
  return ceil_pow(x, 2);
}

// a^k <= xを満たす最大のa^k
uint64_t floor_pow(uint64_t x, uint64_t a){
  assert(x > 0 && a > 1);
  if(a == 2) return uint64_t(1) << (63 - __builtin_clzll(x));
  if(a > 10){
    uint64_t ret = 1;
    while(true){
      if(ret > x / a) return ret;
      ret *= a;
    }
  }
  static std::vector<std::vector<uint64_t>> pow_table(11);
  static uint64_t INF = std::numeric_limits<uint64_t>::max();
  if(pow_table[a].empty()){
    uint64_t tmp = 1;
    pow_table[a].push_back(1);
    while(true){
      if(tmp > INF / a) break;
      pow_table[a].push_back(tmp *= a);
    }
  }
  return *--std::upper_bound(pow_table[a].begin(), pow_table[a].end(), x);
}



// 10 = 10 * 1 + 0
// 10 =  9 * 1 + 1
// 10 =  8 * 1 + 2
// 10 =  7 * 1 + 3
// 10 =  6 * 1 + 4
// 10 =  5 * 2 = 0
// 10 =  4 * 2 + 2
// 10 =  3 * 3 = 1
// 10 =  2 * 5 + 0
// 10 =  1 * 10 + 10

// 商としてありえる数は高々 2 * √x 通り
// また, [dmin, dmax]が存在して, この区間の数で割った商は全て等しく, 区間に含まれない任意の数で割った商とは異なる
// 可能な組{商, dmin, dmax}を列挙
std::vector<std::array<long long, 3>> divrange(long long x){
  if(x == 1) return {{1, 1, 1}};
  std::vector<std::array<long long, 3>> l{{x, 1, 1}}, r{{1, x, x}};
  int ls = 0, rs = 0;
  long long i = 2;
  for(;i*i<=x;i++){
    long long d = x / i;
    if(l[ls][0] != d) l.push_back({d, i, i}), ls++;
    else l[ls][1] = i;
    if(i * i == x) continue;
    if(r[rs][0] != i) r[rs][1] = d + 1, r.push_back({i, d, d}), rs++;
    else r[rs][2] = x;
  }
  if(l[ls][0] == r[rs][0]) l[ls][2] = r[rs][2], r.pop_back();
  std::reverse(r.begin(), r.end());
  r[0][1] = i;
  l.insert(l.end(), r.begin(), r.end());
  return l;
}

// a ^ k <= xを満たす最大のa
uint64_t kth_root_stable(uint64_t x, uint64_t k){
  if(!x) return 0;
  if(k == 1 || x == 1) return x;
  if(k >= 64) return 1;
  uint64_t l = 1, r = x;
  const static uint64_t threshold = std::numeric_limits<uint64_t>::max();
  while(r - l > 1){
    bool f = false;
    uint64_t mid = l + ((r - l) >> 1), z = 1;
    uint64_t lim = threshold / mid;
    for(int i = 0; i < k; i++){
      if(z > lim){
        f = true;
        break;
      }
      z *= mid;
    }
    if(f | (z > x)) r = mid;
    else l = mid;
  }
  return l;
}

// a^k <= x を満たす最大のa
uint64_t kth_root_fast(uint64_t x, uint64_t k){
  if(x <= 1) return (!k ? 1 : x);
  if(k <= 2) return (k <=1 ? !k ? 1 : x : sqrtl(x));
  if(k >= 64||!(x >> k)) return 1;
  const static int sz[8] = {40, 31, 27, 24, 22, 21, 20, 19};
  static std::vector<std::vector<uint64_t>> table;
  if(table.empty()){
    table.resize(40);
    for(int i = 0; i < 40; i++){
      for(uint64_t j = 0; j < 8 && sz[j] > i; j++){
        table[i].push_back((!i ? 1 : table[i - 1][j]) *(j + 3));
      }
    }
  }
  if(k >= 19){
    int ans = 10;
    for(;ans > 2; ans--){
      if(sz[ans - 3]<k || table[k - 1][ans - 3] > x) continue;
      return ans;
    }
    return 2;
  }
  uint64_t r = (k != 3 ? pow(x, (1.0 + 1e-6) / k) : cbrt(x) + 1);
  const static uint64_t threshold = std::numeric_limits<uint64_t>::max();
  while(true){
    uint64_t lim = threshold / r, z = 1;
    for(int i = 0; i < k; i++, z *= r) if(z > lim) goto upper;
    if(z > x) upper: r--;
    else break;
  }
  return r;
}


namespace prime_sieve{
  std::vector<int> primes, min_factor;// 素数, 各数を割り切る最小の素数
  // O(MAX_N loglog MAX_N)
  void init(int MAX_N){
    min_factor.resize(MAX_N + 1, -1);
    for(int i = 2; i <= MAX_N; i++){
      if(min_factor[i] == -1){
        primes.push_back(i);
        min_factor[i] = i;
      }
      for(int p : primes){
        if((long long)p * i > MAX_N || p > min_factor[i]) break;
        min_factor[p * i] = p;
      }
    }
  }
  bool is_prime(int n){
    assert(n < min_factor.size());
    return n == min_factor[n];
  }
  // {{素因数, 数}}, O(log n)
  std::vector<std::pair<int, int>> factorize(int n){
    assert(n < min_factor.size());
    std::vector<std::pair<int, int>> ret;
    while(n > 1){
      int cnt = 0, f = min_factor[n];
      while(n % f == 0){
        n /= f;
        cnt++;
      }
      ret.push_back({f, cnt});
    }
    return ret;
  }
  // 約数列挙, O(√n)
  std::vector<int> divisor(int n){
    auto p = factorize(n);
    std::vector<std::vector<int>> x;
    for(int i = 0; i < p.size(); i++){
      x.push_back(std::vector<int>{1});
      for(int j = 0; j < p[i].second; j++) x[i].push_back(x[i][j] * p[i].first);
    }
    int l = 0, r = 1;
    std::vector<int> ret{1};
    for(int i = 0; i < x.size(); i++){
      for(auto e : x[i]){
        for(int j = l; j < r; j++){
          ret.push_back(ret[j] * e);
        }
      }
      l = r;
      r = ret.size();
    }
    return std::vector<int>(ret.begin() + l, ret.end());
  }
};


std::vector<long long> v{1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,7560,10080,15120,20160,25200,27720,45360,50400,55440,83160,110880,166320,221760,277200,332640,498960,554400,665280,720720,1081080,1441440,2162160,2882880,3603600,4324320,6486480,7207200,8648640,10810800,14414400,17297280,21621600,32432400,36756720,43243200,61261200,73513440,110270160,122522400,147026880,183783600,245044800,294053760,367567200,551350800,698377680,735134400,1102701600,1396755360,2095133040,2205403200,2327925600,2793510720,3491888400,4655851200,5587021440,6983776800,10475665200,13967553600,20951330400,27935107200,41902660800,48886437600,64250746560,73329656400,80313433200,97772875200,128501493120,146659312800,160626866400,240940299600,293318625600,321253732800,481880599200,642507465600,963761198400,1124388064800,1606268664000,1686582097200,1927522396800,2248776129600,3212537328000,3373164194400,4497552259200,6746328388800,8995104518400,9316358251200,13492656777600,18632716502400,26985313555200,27949074753600,32607253879200,46581791256000,48910880818800,55898149507200,65214507758400,93163582512000,97821761637600,130429015516800,195643523275200,260858031033600,288807105787200,391287046550400,577614211574400,782574093100800,866421317361600,1010824870255200,1444035528936000,1516237305382800,1732842634723200,2021649740510400,2888071057872000,3032474610765600,4043299481020800,6064949221531200,8086598962041600,10108248702552000,1212898443062400,18194847664593600,20216497405104000,24259796886124800,30324746107656000,36389695329187200,48519593772249600,60649492215312000,72779390658374400,74801040398884800,106858629141264000,112201560598327200,149602080797769600,224403121196654400,299204161595539200,374005201994424000,448806242393308800,673209363589963200,748010403988848000,897612484786617600};

std::vector<long long> ans{1,2,3,4,6,8,9,10,12,16,18,20,24,30,32,36,40,48,60,64,72,80,84,90,96,100,108,120,128,144,160,168,180,192,200,216,224,240,256,288,320,336,360,384,400,432,448,480,504,512,576,600,640,672,720,768,800,864,896,960,1008,1024,1152,1200,1280,1344,1440,1536,1600,1680,1728,1792,1920,2016,2048,2304,2400,2688,2880,3072,3360,3456,3584,3600,3840,4032,4096,4320,4608,4800,5040,5376,5760,6144,6720,6912,7168,7200,7680,8064,8192,8640,9216,10080,10368,10752,11520,12288,12960,13440,13824,14336,14400,15360,16128,16384,17280,18432,20160,20736,21504,23040,24576,25920,26880,27648,28672,28800,30720,32256,32768,34560,36864,40320,41472,43008,46080,48384,49152,51840,53760,55296,57600,61440,62208,64512,65536,69120,73728,80640,82944,86016,92160,96768,98304,103680
};

// 高度合成数(N以下の数の中で最も多い約数を持つ数)
// {N以下の高度合成数, その約数}
std::pair<long long, long long> highly_composite_number(long long N){
  assert(0 < N && N <= 1000000000000000000);
  int idx = upper_bound(v.begin(), v.end(), N) - v.begin() - 1;
  assert(idx != 0);
  return {v[idx], ans[idx]};
}
#line 9 ".lib/data_structure/segment_tree/dual_segment_tree.hpp"


// 区間set, これまでにsetした物の中ならどれかを取得
struct range_set_get_any{
  template<typename Val>
  static Val id1(){
    return nullptr;
  }
  template<typename Lazy>
  static Lazy id2(){
    return nullptr;
  }
  template<typename Lazy>
  static Lazy propagate(Lazy l, Lazy x){
    return (x == nullptr ? l : x);
  }
  template<typename Val, typename Lazy>
  static Val apply(Val v, Lazy x, int l, int r){
    return (x == nullptr ? v : x);
  }
};

template<typename commutative_group, typename Val, typename Lazy>
struct dual_segment_tree{
  int N, M;
  std::vector<Val> val;
  std::vector<Lazy> lazy;

  dual_segment_tree(){}
  dual_segment_tree(int n): N(n), M(ceil_2_pow(N)),
  val(n, commutative_group::template id1<Val>()), lazy(2 * M - 1, commutative_group::template id2<Lazy>()){}
  dual_segment_tree(int n, Val v): N(n), M(ceil_2_pow(N)),
  val(n, v), lazy(2 * M - 1, commutative_group::template id2<Lazy>()){}
  dual_segment_tree(const std::vector<Val> v):N(v.size()), M(ceil_2_pow(N)),
  val(v), lazy(2 * M - 1, commutative_group::template id2<Lazy>()){}

  Val get(int k){
    assert(0 <= k && k < N);
    int t = k;
    t += M - 1;
    Lazy lz = lazy[t];
    while(t){
      t = (t - 1) >> 1;
      lz = commutative_group::template propagate<Lazy>(lz, lazy[t]);
    }
    return commutative_group::apply(val[k], lz, k, k + 1);
  }
  void update(int l, int r, Lazy x){
    l = std::max(l, 0), r = std::min(r, N);
    assert(l <= r);
    l += M, r += M;
    while(l < r){
      if(l & 1) lazy[l - 1] = commutative_group::template propagate<Lazy>(lazy[l - 1], x), l++;
      if(r & 1) r--, lazy[r - 1] = commutative_group::template propagate<Lazy>(lazy[r - 1], x);
      l >>= 1;
      r >>= 1;
    }
  }
};
#line 6 ".lib/graph/cycle.hpp"

// O(V + E)
// ショートカットが無い閉路を1つ返す, 閉路が無い場合は空のvector
// 自己辺はサイクルと見なさない(含めたい場合, e.from = e.toの辺を探す)
// 多重辺があっても良い
// 無向辺の場合辺にidをつけて逆流しないようにする
template<typename edge>
void cycle_detection_any_noshortcut(int cur, vec<vec<edge>> &g, vec<bool> &use, vec<int> &in, vec<edge> &E, vec<edge> &res, int last_edge_id){
  if(in[cur] >= 0){
    int s = 0;
    while(E[s].from() != cur) s++;// cur->curの閉路
    std::queue<edge> shortcut;
    std::fill(use.begin(), use.end(), 0);
    while(res.empty()){
      use[cur] = true;
      int skip_in = -1, end_in = -1;
      edge skip_e = g[cur][0], end_e = g[cur][0];
      for(edge &e : g[cur]){
        int to = e.to();
        if(in[to] == -1 || (last_edge_id == e.id())) continue;
        if(in[to] > in[cur] && skip_in < in[to]) skip_in = in[to], skip_e = e;
        if(in[to] < in[cur] && use[to] && end_in < in[to]) end_in = in[to], end_e = e;
      }
      if(end_in != -1){
        int to = end_e.to();
        while(E[s].from() != to) s++;
        while(E.back().to() != cur) E.pop_back();
        while(!shortcut.empty() && in[shortcut.front().to()] <= in[to]) shortcut.pop();
        E.push_back(end_e);
        while(s != E.size()){
          int srank = (shortcut.empty() ? g.size() : in[shortcut.front().from()]);
          while(s != E.size() && in[E[s].from()] < srank) res.push_back(E[s++]);
          if(!shortcut.empty()){
            int trank = in[shortcut.front().to()];
            res.push_back(shortcut.front());
            shortcut.pop();
            while(in[E[s].from()] < trank) s++;
          }
        }
        return;
      }
      if(in[cur] + 1 != skip_in) shortcut.push(skip_e);
      cur = skip_e.to();
      last_edge_id = skip_e.id();
    }
    return;
  }
  in[cur] = E.size();
  for(edge &e : g[cur]){
    if(e.to() == cur) continue;
    if(!use[e.to()] && res.empty() && (e.id() == -1 || e.id() != last_edge_id)){
      E.push_back(e);
      cycle_detection_any_noshortcut<edge>(e.to(), g, use, in, E, res, e.id());
      E.pop_back();
    }
  }
  use[cur] = true;
  in[cur] = -1;
}

template<typename edge>
vec<edge> cycle_detection_any_noshortcut(vec<vec<edge>> &g){
  int n = g.size();
  //for(int i = 0; i < n; i++) for(auto &e : g[i]) if(e.to() == e.from()) return {e}; 自己辺をサイクルと見なすか
  vec<bool> use(n, false);
  vec<int> in(n, -1);
  vec<edge> res, E;
  for(int i = 0; i < n; i++){
    if(use[i]) continue;
    cycle_detection_any_noshortcut<edge>(i, g, use, in, E, res, -1);
    if(!res.empty()) break;
  }
  return res;
}
// !
// vを含む閉路を1つ返す O(V + E)
// 無向辺の場合辺にidをつけて逆流しないようにする
template<typename edge>
vec<edge> cycle_detection_v(vec<vec<edge>> &g, int v){
  int n = g.size();
  vec<edge> E;
  vec<bool> used(n, false);
  bool is_end = false;
  auto cycle_dfs = [&](auto &&cycle_dfs, int cur, int last_edge_id)->void{
    used[cur] = true;
    for(edge &e : g[cur]){
      //if(last_edge_id != -1 && last_edge_id == e.id()) continue; 自己辺もサイクルと見なす場合
      if(e.to() == cur || last_edge_id != -1 && last_edge_id == e.id()) continue;
      if(e.to() == v){
        E.push_back(e);
        is_end = true;
        return;
      }
      if(used[e.to()]) continue;
      E.push_back(e);
      cycle_dfs(cycle_dfs, e.to(), e.id());
      if(is_end) return;
      E.pop_back();
    }
  };
  cycle_dfs(cycle_dfs, v, -1);
  return E;
}

/*
template<typename edge>
vec<edge> directed_cycle_detection_v_noshortcut(vec<vec<edge>> &g, int v){

}
*/

template<typename edge>
vec<edge> undirected_cycle_detection_v_noshortcut(vec<vec<edge>> &g, int v){
  int n = g.size();
  auto E = cycle_detection_v<edge>(g, v);
  if(E.empty()) return E;
  vec<int> in(n, -1);
  for(int i = 0; i < E.size(); i++) in[E[i].from()] = i;
  vec<edge> res;
  int s = v, last_edge_id = E.back().id();
  while(true){
    int next_in = in[s] + 1;
    edge next_e = E[in[s]];
    for(edge &e : g[s]){
      if(in[e.to()] == -1 || e.id() == last_edge_id) continue;
      //if(e.to() == v){自己辺を含む場合
      if(e.to() != s && e.to() == v){// 終了
        res.push_back(e);
        return res;
      }
      if(in[e.to()] > next_in){
        next_in = in[e.to()];
        next_e = e;
      }
    }
    res.push_back(next_e);
    s = next_e.to();
    last_edge_id = next_e.id();
  }
}

// ! グラフが連結でない場合

// res[v] := vを含む閉路 O(V^2 + Elog^2V)
// 全ての辺に[0, E)のuniqueな値を振っておく
template<typename edge>
vec<vec<edge>> undirected_cycle_detection_vv(vec<vec<edge>> &g){
  int n = g.size();
  tree<edge> t = bfs_tree<edge>(g, 0);
  vec<bool> used_edge{0};
  for(int i = 0; i < n; i++){
    for(edge &e : t.g[i]){
      assert(0 <= e.id() && e.id() <= 1e7);
      while(used_edge.size() <= e.id()) used_edge.resize(used_edge.size() << 1);
      used_edge[e.id()] = true;
    }
  }
  t.hld_build();
  t.bfs_build();
  dual_segment_tree<range_set_get_any, edge*, edge*> seg(n, nullptr);
  for(int i = 0; i < n; i++){
    for(edge &e : g[i]){
      if(e.id() >= used_edge.size() || !used_edge[e.id()]){// bfs木に含まれない
        for(auto [l, r] : t.hld_p->unordered_path(e.from(), e.to())) seg.update(l, r, &e);
        if(e.id() < used_edge.size()) used_edge[e.id()] = true;
      }
    }
  }
  vec<vec<edge>> res(n);
  for(int i = 0; i < n; i++){
    if(!res[i].empty()) continue;
    edge *e = seg.get(t.hld_p->index_vertex(i));
    if(!e) continue;// iを含む閉路が無い
    vec<edge> E;
    int a = e->from(), b = e->to(), l = t.hld_p->lca(a, b);
    while(a != l){
      E.push_back(t.bfs_p->get_parent_edge(a));
      a = t.parent[a];
    }
    std::reverse(E.begin(), E.end());
    E.push_back(*e);
    while(b != l){
      E.push_back(t.bfs_p->get_parent_edge(b).reverse());
      b = t.parent[b];
    }
    for(edge &e : E) if(res[e.from()].empty()) res[e.from()] = E;
  }
  return res;
}

// O(V(V + E)logV)
template<typename edge>
std::pair<typename edge::weight, vec<edge>> mincost_cycle_fast(const vec<vec<edge>> &g, bool directed){
  using weight = typename edge::weight;
  using pdv = std::pair<weight, int>;
  static constexpr weight inf = std::numeric_limits<weight>::max() / 2;

  auto chmin = [&](weight &a, weight b)->bool{
    if(a > b){
      a = b;
      return true;
    }
    return false;
  };
  int n = g.size();
  std::priority_queue<pdv, vec<pdv>, std::greater<pdv>> que;
  vec<vec<edge>> cpg = g;
  for(int v = 0; v < n; v++) std::sort(cpg[v].begin(), cpg[v].end(), [](edge &a, edge &b){return a.to() < b.to();});

  weight ans = inf;
  vec<edge> E;
  for(int v = n - 1; v >= 0; v--){
    vec<weight> dist(v + 1, inf);
    dist[v] = edge::z();
    que.push({edge::z(), v});
    vec<edge> par(v), unused;
    while(!que.empty()){
      auto [d, u] = que.top();
      que.pop();
      if(dist[u] < d) continue;
      for(int i = 0; i < cpg[u].size(); i++){
        int to = cpg[u][i].to();
        if(to > v){
          cpg[u].pop_back();
          continue;
        }
        weight nxtd = d + cpg[u][i].wei();
        if(chmin(dist[to], nxtd)){
          par[to] = cpg[u][i];
          que.push({nxtd, to});
        }else if(par[u].id() != cpg[u][i].id()) unused.push_back(cpg[u][i]);
      }
    }
    weight pre_ans = ans;
    edge tmp_edge;
    if(!directed){
      for(edge &e : unused){
        if(dist[e.from()] == inf || dist[e.to()] == inf) continue;
        if(e.from() == e.to()){
          //if(e.to() == v && chmin(ans, e.wei())) tmp_edge = e; 自己辺をサイクルと見なす場合
          continue;
        }
        if(chmin(ans, e.wei() + dist[e.from()] + dist[e.to()])) tmp_edge = e;
      }
    }else{
      for(edge &e : unused){
        if(dist[e.from()] == inf) continue;
        //if(e.to() == v && chmin(ans, e.wei() + dist[e.from()])) tmp_edge = e; 自己辺をサイクルと見なす場合
        if(e.from() != v && e.to() == v && chmin(ans, e.wei() + dist[e.from()])) tmp_edge = e;
      }
    }
    if(ans < pre_ans){
      E.clear();
      int a = tmp_edge.from();
      while(a != v){
        E.push_back(par[a]);
        a = par[a].from();
      }
      std::reverse(E.begin(), E.end());
      E.push_back(tmp_edge);
      a = tmp_edge.to();
      while(a != v){
        E.push_back(par[a].reverse());
        a = par[a].from();
      }
    }
  }
  return {ans, E};
}
#line 5 "a.cpp"

int main(){
  io_init();
  int t;
  std::cin >> t;
  int n, m;
  std::cin >> n >> m;
  weighted_labeled_graph<ll> g(n);

  range(i, 0, m){
    int a, b, c;
    std::cin >> a >> b >> c;
    a--, b--;
    g.add_edge(a, {a, b, c, i});
    if(!t) g.add_edge(b, {b, a, c, i});
  }
  auto [ans, E] = mincost_cycle_fast(g.g, t);
  static constexpr ll inf = std::numeric_limits<ll>::max() / 2;
  std::cout << (ans == inf ? -1 : ans) << '\n';
  //for(auto &e : E) std::cout << e.from() << " " << e.to() << " " << e.wei() << '\n';
}
0