#include <vector>
#include <stack>
#include <queue>
#include <list>
#include <bitset>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <numeric>
#include <iostream>
#include <iomanip>
#include <string>
#include <chrono>
#include <random>
#include <cmath>
#include <cassert>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <sstream>

using namespace std;



int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);


    int n, m;
    cin >> n >> m;
    long long X;
    cin >> X;
    vector<pair<long long,pair<int,int>>> edges;
    
    vector<bool> used(m, false);

    for (int i = 0; i < m; ++i) {
        int u, v, w;
        cin >> u >> v >> w;
        --u, --v;
        edges.emplace_back(w, make_pair(u, v));
    }

    vector<int> pars(n, -1);
    function<int(int)> find  = [&](int x) {
        return pars[x] < 0 ? x : pars[x] = find(pars[x]);
    };
    auto unite = [&](int x, int y) {
        x = find(x), y = find(y);
        if (x == y) {
            return false;
        }
        if (pars[x] < pars[y]) {
            swap(x, y);
        }
        pars[y] += pars[x];
        pars[x] = y;
        return true;
    };

    
    sort(edges.begin(),edges.end());
    vector<vector<pair<int, long long>>> graph(n);
    long long minW = 0;
    for (int i = 0; i < m; ++i) {
        auto& e = edges[i];
        int u = e.second.first, v = e.second.second;
        long long w = e.first;

        if (unite(u, v)) {
            minW += w;
            graph[u].emplace_back(v, w);
            graph[v].emplace_back(u, w);
            used[i] = true;
        }
    }

    // cout << "minW " << minW  << endl;

    if (minW > X) {
        cout << 0 << '\n';
        return 0;
    }

    vector<long long> WS;
    vector<int> que(n + 123);
    const long long INF = 1LL << 60;
    vector<long long> dis(n, -INF);
    vector<bool> visited(n, false);
    for (int i = 0; i < m; ++i) {
        if (!used[i]) {
            int s = edges[i].second.first;
            int t = edges[i].second.second;

            int sz = 0;
            que[sz++] = s;
            dis[s] = 0;
            visited[s] = true;
            for (int j = 0; j < sz; ++j) {
                int u = que[j];
                for (auto& e : graph[u]) {
                    int v = e.first;
                    if (visited[v]) {
                        continue;
                    }
                    visited[v] = true;
                    long long w = e.second;
                    dis[v] = max(dis[u], w);
                    que[sz++] = v;
                    if (v == t) {
                        j = sz;
                        break;
                    }
                }
            }

            // cout << i << " " << edges[i].first << " " << dis[t] << endl;
            WS.push_back(edges[i].first - dis[t]);
            for (int j = 0; j < sz; ++j) {
                int x = que[j];
                visited[x] = false;
                dis[x] = -INF;
            }
        }
    }

    sort(WS.begin(), WS.end());

    int less = 0, eq = 0, greater = 0;

    for (auto x : WS) {
        if (x < X - minW) {
            ++less;
        } else if (x == X - minW) {
            ++eq;
        } else {
            ++greater;
        }
    }

    // cout << minW << " " << less << " " << eq << " " << greater << endl; 
    const long long MOD = 1000000007;
    vector<long long> pow2(m + 1, 1);
    for (int i = 1; i <= m; ++i) {
        pow2[i] = pow2[i - 1] * 2 % MOD;
    }

    long long res = 0;
    {
        (res += 2 * (pow2[eq] - 1) % MOD * pow2[greater] % MOD) %= MOD;
    }
    if (X == minW) {
        (res += (pow2[n - 1] - 2 + MOD) % MOD * pow2[m - (n - 1)] % MOD) %= MOD;
    }

    cout << res << '\n';


    return 0;
}

Measured memory_bytes: 384