#pragma region head
    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    using vi = vector<int>;
    using vll = vector<ll>;
    using pi = pair<int, int>;
    using pll = pair<ll,ll>;
    template <class T> using vv = vector<vector<T>>;
    #define rep(i,n) for(int i = 0; i < (int)(n); i++)
    #define repi(i,a,b) for(int i = (int)(a); i < (int)(b); i++)
    #define rrep(i,n) for(int i = (int)(n)-1; i >= 0; i--)
    #define rrepi(i,a,b) for(int i = (int)(b)-1; i >= (int)(a); i--)
    const int INF = 1002003004;
    const ll LINF = 1002003004005006007ll;
    struct preprocess{preprocess()
    {cin.tie(nullptr);ios::sync_with_stdio(false);cout<<fixed<<setprecision(20);}}____;
#pragma endregion head

#pragma region library
const int MOD = 1000000007;
struct mint {
  ll x; // typedef long long ll;
  mint(ll x=0):x((x%MOD+MOD)%MOD){}
  mint operator-() const { return mint(-x);}
  mint& operator+=(const mint a) {
    if ((x += a.x) >= MOD) x -= MOD;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += MOD-a.x) >= MOD) x -= MOD;
    return *this;
  }
  mint& operator*=(const mint a) {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint operator+(const mint a) const {
    mint res(*this);
    return res+=a;
  }
  mint operator-(const mint a) const {
    mint res(*this);
    return res-=a;
  }
  mint operator*(const mint a) const {
    mint res(*this);
    return res*=a;
  }
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }
  // for prime MOD
  mint inv() const {
    return pow(MOD-2);
  }
  mint& operator/=(const mint a) {
    return (*this) *= a.inv();
  }
  mint operator/(const mint a) const {
    mint res(*this);
    return res/=a;
  }
};
ostream& operator<< (ostream& os, const mint& value) {
  os << value.x;
  return os;
}


template <class T>
struct Edge{
    int src;
    int to;
    T cost;
    Edge(int t,T c) : to(t),cost(c) {}
    Edge(int src, int t,T c) : src(src),to(t),cost(c) {}
};
template<class T> using WeightedGraph = vector<vector<Edge<T>>>;
// Time Complexity: faster than O(logN)[O(ArkInv(N))]
// UnionFind.data: if minus -> size of subtree (node is root)
// if plus -> parent of the node
struct UnionFind {
    vector<int> data;
    UnionFind(int sz){
        data.assign(sz,-1);
    }
    int find(int x){
        if(data[x]<0) return x;
        return data[x]=find(data[x]);
    }
    bool unite(int x, int y){
        x = find(x); y = find(y);
        if(x==y) return false;
        if(data[x]>data[y]) swap(x,y);
        data[x]+=data[y];
        data[y]=x;
        return true;
    }
    int size(int x){
        return (-data[find(x)]);
    }
    bool same(int x,int y){
        return find(x)==find(y);
    }
};

#pragma endregion library
bool dfs(WeightedGraph<ll>& g, set<ll>& vc, int u, int c, ll cst,int p=-1){
    if(u==c) return true;
    for(auto e:g[u]){
        if(e.to == p) continue;
        if(dfs(g,vc,e.to,c,cst,u)){
            vc.emplace(cst-e.cost);
            return true;
        }
    }
    return false;
}

// Dependency: Union-Find,Graph Template
// Time complexity: O(E logV)
mint kruskal(vector<Edge<ll>>& es,int v,ll aim){
    sort(es.begin(),es.end(),[](Edge<ll>& e1,Edge<ll>& e2){
        return e1.cost < e2.cost;
    });
    UnionFind uf(v);
    ll cost = 0;
    int alt = 0;
    int any = 0;
    WeightedGraph<ll> g(v);
    vector<set<ll>> vs;
    for(auto& e: es){
        if(!uf.same(e.src,e.to)){
            uf.unite(e.src,e.to);
            cost += e.cost;
            g[e.src].emplace_back(e.to,e.cost);
            g[e.to].emplace_back(e.src,e.cost);
        } else {
            set<ll> vc;
            dfs(g,vc,e.src,e.to,e.cost);
            vs.emplace_back(vc);
        }
    }
    if(cost==aim){
        for(auto& s: vs){
        auto it = s.find(aim-cost);
        if(it!=s.end()) alt++;
        }
        int mstv = v-1+alt;
        return (mint(2).pow(mstv)-2)*(mint(2).pow(es.size()-mstv));
    } 
    if(cost>aim) return 0;
    for(auto& s: vs){
        auto it = s.begin();
        if(*it==aim-cost) alt++;
        if(*it>aim-cost) any++;
    }
    return (mint(2).pow(any))*(mint(2).pow(alt)-1)*2;
}



int main(){
    int n,m; ll x; cin >> n >> m >> x;
    vector<Edge<ll>> es;
    rep(i,m){
        int u,v; ll c; cin >> u >> v >> c;
        u--; v--;
        es.emplace_back(u,v,c);
    }
    mint ans = kruskal(es,n,x);
    cout << ans << '\n';
    
}

Measured memory_bytes: 16640