Problem p03405 (C++)

Buggy submission (status: Runtime Error):
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<long long, long long>;
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define all(x) (x).begin(), (x).end()
constexpr char ln = '\n';
constexpr long long MOD = 1000000007;
// constexpr long long MOD = 998244353;
template <class T1, class T2> inline bool chmax(T1 &a, T2 b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T1, class T2> inline bool chmin(T1 &a, T2 b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
inline int popcount(int x) { return __builtin_popcount(x); }
inline int popcount(long long x) { return __builtin_popcountll(x); }
void print() { cout << "\n"; }
template <class T, class... Args> void print(const T &x, const Args &...args) {
  cout << x << " ";
  print(args...);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <typename T> struct edge {
  int src, to;
  T cost;
  int id;

  edge() {}
  edge(int to, T cost) : src(-1), to(to), cost(cost), id(-1) {}
  edge(int src, int to, T cost) : src(src), to(to), cost(cost), id(-1) {}
  edge(int src, int to, T cost, int id)
      : src(src), to(to), cost(cost), id(id) {}
  bool operator<(const edge &e) const { return cost < e.cost; }
};

struct UnionFind {
  int N;
  vector<int> node;

  UnionFind() {}
  UnionFind(int N) : N(N), node(N, -1) {}

  void init(int x) {
    node.assign(x, -1);
    N = x;
  }

  bool merge(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (node[x] > node[y])
      swap(x, y);
    node[x] += node[y];
    node[y] = x;
    N--;
    return true;
  }

  bool same(int x, int y) { return root(x) == root(y); }

  int root(int x) {
    if (node[x] < 0)
      return x;
    return node[x] = root(node[x]);
  }

  int size(int x) { return -node[root(x)]; }

  int count() const { return N; }
};

template <uint_fast64_t Modulus> struct ModInt {
  using u64 = uint_fast64_t;

  u64 a;

  constexpr ModInt(const long long x = 0) noexcept
      : a(x >= 0 ? x % Modulus : (Modulus - (-x) % Modulus) % Modulus) {}
  constexpr u64 &value() noexcept { return a; }
  constexpr const u64 &value() const noexcept { return a; }
  constexpr ModInt operator+(const ModInt rhs) const noexcept {
    return ModInt(*this) += rhs;
  }
  constexpr ModInt operator-(const ModInt rhs) const noexcept {
    return ModInt(*this) -= rhs;
  }
  constexpr ModInt operator*(const ModInt rhs) const noexcept {
    return ModInt(*this) *= rhs;
  }
  constexpr ModInt operator/(const ModInt rhs) const noexcept {
    return ModInt(*this) /= rhs;
  }
  constexpr ModInt operator^(const long long rhs) const noexcept {
    return ModInt(*this) ^= rhs;
  }
  constexpr bool operator==(const ModInt &rhs) const noexcept {
    return a == rhs.a;
  }
  constexpr bool operator!=(const ModInt &rhs) const noexcept {
    return a != rhs.a;
  }
  constexpr ModInt &operator+=(const ModInt rhs) noexcept {
    a += rhs.a;
    if (a >= Modulus) {
      a -= Modulus;
    }
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt rhs) noexcept {
    if (a < rhs.a) {
      a += Modulus;
    }
    a -= rhs.a;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt rhs) noexcept {
    a = a * rhs.a % Modulus;
    return *this;
  }
  constexpr ModInt &operator/=(ModInt rhs) noexcept {
    u64 exp = Modulus - 2;
    while (exp) {
      if (exp & 1)
        *this *= rhs;
      exp >>= 1;
      rhs *= rhs;
    }
    return *this;
  }
  constexpr ModInt &operator^=(long long exp) noexcept {
    ModInt rhs = a;
    a = 1;
    while (exp) {
      if (exp & 1)
        *this *= rhs;
      exp >>= 1;
      rhs *= rhs;
    }
    return *this;
  }

  friend ostream &operator<<(ostream &os, const ModInt &rhs) noexcept {
    return os << rhs.a;
  }
  friend istream &operator>>(istream &is, ModInt &rhs) noexcept {
    long long a;
    is >> a;
    rhs = a;
    return is;
  }
};

using mint = ModInt<MOD>;

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int N, M;
  cin >> N >> M;
  ll X;
  cin >> X;
  vector<edge<ll>> E(M);
  rep(i, M) {
    int u, v, w;
    cin >> u >> v >> w;
    --u;
    --v;
    E[i] = edge<ll>(u, v, w);
  }

  sort(all(E));
  UnionFind uf(N);
  vector<bool> used(N);
  vector<vector<edge<ll>>> MST(N);
  ll Y = 0;
  rep(i, M) {
    if (uf.merge(E[i].src, E[i].to)) {
      used[i] = 1;
      MST[E[i].src].emplace_back(E[i].to, E[i].cost);
      MST[E[i].to].emplace_back(E[i].src, E[i].cost);
      Y += E[i].cost;
    }
  }
  if (Y > X) {
    cout << 0 << ln;
    return 0;
  }

  int cnt = N - 1, cnt2 = 0;
  rep(i, M) {
    if (used[i])
      continue;
    int s = E[i].src;
    int t = E[i].to;
    vector<ll> path;
    auto dfs = [&](auto &&self, int v, int pv) -> bool {
      if (v == t)
        return true;
      for (auto &e : MST[v]) {
        if (e.to == pv)
          continue;
        path.emplace_back(e.cost);
        if (self(self, e.to, v))
          return true;
        path.pop_back();
      }
      return false;
    };
    dfs(dfs, s, -1);
    ll val = *max_element(all(path));
    if (Y == X) {
      if (val == E[i].cost)
        cnt++;
    } else {
      if (Y - val + E[i].cost < X)
        cnt++;
      else if (Y - val + E[i].cost == X)
        cnt2++;
    }
  }

  mint ans = 1;
  if (Y == X) {
    rep(i, cnt) ans *= 2;
    ans -= 2;
    rep(i, M - cnt) ans *= 2;
  } else {
    rep(i, cnt2) ans *= 2;
    ans -= 1;
    rep(i, M - cnt - cnt2) ans *= 2;
    ans *= 2;
  }

  cout << ans << ln;
}


Fixed submission:
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<long long, long long>;
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define all(x) (x).begin(), (x).end()
constexpr char ln = '\n';
constexpr long long MOD = 1000000007;
// constexpr long long MOD = 998244353;
template <class T1, class T2> inline bool chmax(T1 &a, T2 b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T1, class T2> inline bool chmin(T1 &a, T2 b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
inline int popcount(int x) { return __builtin_popcount(x); }
inline int popcount(long long x) { return __builtin_popcountll(x); }
void print() { cout << "\n"; }
template <class T, class... Args> void print(const T &x, const Args &...args) {
  cout << x << " ";
  print(args...);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <typename T> struct edge {
  int src, to;
  T cost;
  int id;

  edge() {}
  edge(int to, T cost) : src(-1), to(to), cost(cost), id(-1) {}
  edge(int src, int to, T cost) : src(src), to(to), cost(cost), id(-1) {}
  edge(int src, int to, T cost, int id)
      : src(src), to(to), cost(cost), id(id) {}
  bool operator<(const edge &e) const { return cost < e.cost; }
};

struct UnionFind {
  int N;
  vector<int> node;

  UnionFind() {}
  UnionFind(int N) : N(N), node(N, -1) {}

  void init(int x) {
    node.assign(x, -1);
    N = x;
  }

  bool merge(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (node[x] > node[y])
      swap(x, y);
    node[x] += node[y];
    node[y] = x;
    N--;
    return true;
  }

  bool same(int x, int y) { return root(x) == root(y); }

  int root(int x) {
    if (node[x] < 0)
      return x;
    return node[x] = root(node[x]);
  }

  int size(int x) { return -node[root(x)]; }

  int count() const { return N; }
};

template <uint_fast64_t Modulus> struct ModInt {
  using u64 = uint_fast64_t;

  u64 a;

  constexpr ModInt(const long long x = 0) noexcept
      : a(x >= 0 ? x % Modulus : (Modulus - (-x) % Modulus) % Modulus) {}
  constexpr u64 &value() noexcept { return a; }
  constexpr const u64 &value() const noexcept { return a; }
  constexpr ModInt operator+(const ModInt rhs) const noexcept {
    return ModInt(*this) += rhs;
  }
  constexpr ModInt operator-(const ModInt rhs) const noexcept {
    return ModInt(*this) -= rhs;
  }
  constexpr ModInt operator*(const ModInt rhs) const noexcept {
    return ModInt(*this) *= rhs;
  }
  constexpr ModInt operator/(const ModInt rhs) const noexcept {
    return ModInt(*this) /= rhs;
  }
  constexpr ModInt operator^(const long long rhs) const noexcept {
    return ModInt(*this) ^= rhs;
  }
  constexpr bool operator==(const ModInt &rhs) const noexcept {
    return a == rhs.a;
  }
  constexpr bool operator!=(const ModInt &rhs) const noexcept {
    return a != rhs.a;
  }
  constexpr ModInt &operator+=(const ModInt rhs) noexcept {
    a += rhs.a;
    if (a >= Modulus) {
      a -= Modulus;
    }
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt rhs) noexcept {
    if (a < rhs.a) {
      a += Modulus;
    }
    a -= rhs.a;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt rhs) noexcept {
    a = a * rhs.a % Modulus;
    return *this;
  }
  constexpr ModInt &operator/=(ModInt rhs) noexcept {
    u64 exp = Modulus - 2;
    while (exp) {
      if (exp & 1)
        *this *= rhs;
      exp >>= 1;
      rhs *= rhs;
    }
    return *this;
  }
  constexpr ModInt &operator^=(long long exp) noexcept {
    ModInt rhs = a;
    a = 1;
    while (exp) {
      if (exp & 1)
        *this *= rhs;
      exp >>= 1;
      rhs *= rhs;
    }
    return *this;
  }

  friend ostream &operator<<(ostream &os, const ModInt &rhs) noexcept {
    return os << rhs.a;
  }
  friend istream &operator>>(istream &is, ModInt &rhs) noexcept {
    long long a;
    is >> a;
    rhs = a;
    return is;
  }
};

using mint = ModInt<MOD>;

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int N, M;
  cin >> N >> M;
  ll X;
  cin >> X;
  vector<edge<ll>> E(M);
  rep(i, M) {
    int u, v, w;
    cin >> u >> v >> w;
    --u;
    --v;
    E[i] = edge<ll>(u, v, w);
  }

  sort(all(E));
  UnionFind uf(N);
  vector<bool> used(M);
  vector<vector<edge<ll>>> MST(N);
  ll Y = 0;
  rep(i, M) {
    if (uf.merge(E[i].src, E[i].to)) {
      used[i] = 1;
      MST[E[i].src].emplace_back(E[i].to, E[i].cost);
      MST[E[i].to].emplace_back(E[i].src, E[i].cost);
      Y += E[i].cost;
    }
  }
  if (Y > X) {
    cout << 0 << ln;
    return 0;
  }

  int cnt = N - 1, cnt2 = 0;
  rep(i, M) {
    if (used[i])
      continue;
    int s = E[i].src;
    int t = E[i].to;
    vector<ll> path;
    auto dfs = [&](auto &&self, int v, int pv) -> bool {
      if (v == t)
        return true;
      for (auto &e : MST[v]) {
        if (e.to == pv)
          continue;
        path.emplace_back(e.cost);
        if (self(self, e.to, v))
          return true;
        path.pop_back();
      }
      return false;
    };
    dfs(dfs, s, -1);
    ll val = *max_element(all(path));
    if (Y == X) {
      if (val == E[i].cost)
        cnt++;
    } else {
      if (Y - val + E[i].cost < X)
        cnt++;
      else if (Y - val + E[i].cost == X)
        cnt2++;
    }
  }

  mint ans = 1;
  if (Y == X) {
    rep(i, cnt) ans *= 2;
    ans -= 2;
    rep(i, M - cnt) ans *= 2;
  } else {
    rep(i, cnt2) ans *= 2;
    ans -= 1;
    rep(i, M - cnt - cnt2) ans *= 2;
    ans *= 2;
  }

  cout << ans << ln;
}