#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007

long long modpow(long long n, long long r) {
    n %= mod, r %= (mod-1);
    if (!n) return 0;
    long long ret = 1; long long tmp = n;
    while (r != 0) {
        if (r % 2) ret *= tmp;
        tmp *= tmp; tmp %= mod; ret %= mod;
        r /= 2;
    }
    return ret;
}

// one-based numbering
struct UnionFind {
    vector<int> data;
    // i: (data[i] < 0) -> group size, (data[i] > 0) -> parent;
    UnionFind(int n) {
        data.resize(n+1, -1);
    }
    int find(int x) {
        if(data[x] < 0) return x;
        else return data[x] = find(data[x]);
    }
    int size(int x) {
        return -data[find(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;
    }
    bool same(int x, int y) {
        x = find(x); y = find(y);
        return x == y;
    }
};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, m; cin >> n >> m;
    long long x; cin >> x;
    using edge = array<long long, 3>;
    vector<edge> e;
    for (int i = 0; i < m; i++) {
        long long u, v, w;
        cin >> u >> v >> w;
        e.push_back({w, u, v});
    }
    sort(e.begin(), e.end());
    vector<set<long long>> g(n+1);
    UnionFind uf(n);
    long long curr = 0;
    vector<edge> w;
    vector<vector<pair<int, long long>>> a(n+1);
    for (auto &arr: e) {
        if (uf.same(arr[1], arr[2])) {
            w.emplace_back(arr);
            continue;
        }
        curr += arr[0];
        uf.unite(arr[1], arr[2]);
        a[arr[1]].emplace_back(arr[2], arr[0]);
        a[arr[2]].emplace_back(arr[1], arr[0]);
    }
    if (curr > x) {
        cout << 0 << "\n";
        return 0;
    } else if (curr < x) {
        long long cnt = 0, cnt2 = 0;
        for (int i = 1; i <= n; i++) {
            vector<long long> maxi(n+1, 0);
            auto dfs = [&](auto f, int curr, int prev) -> void {
                for (auto &to: a[curr]) {
                    if (to.first == prev) continue;
                    maxi[to.first] = max(maxi[curr], to.second);
                    f(f, to.first, curr);
                }
            };
            dfs(dfs, i, -1);
            for (auto &arr: w) {
                if (arr[1] != i && arr[2] != i) continue;
                auto c = arr[1] ^ i ^ arr[2];
                if (curr + arr[0] - maxi[c] == x) cnt++;
                if (curr + arr[0] - maxi[c] > x) cnt2++;
            }
        }
        assert(cnt % 2 == 0 && cnt2 % 2 == 0);
        cnt /= 2, cnt2 /= 2;
        cout << (modpow(2, cnt) - 1) * modpow(2, cnt2) * 2 % mod << "\n";
    } else if (curr == x) {
        set<edge> s; int cnt = 0;
        for (int i = 1; i <= n; i++) {
            vector<long long> maxi(n+1, 0);
            auto dfs = [&](auto f, int curr, int prev) -> void {
                for (auto &to: a[curr]) {
                    if (to.first == prev) continue;
                    maxi[to.first] = max(maxi[curr], to.second);
                    f(f, to.first, curr);
                }
            };
            dfs(dfs, i, -1);
            for (auto &arr: w) {
                if (arr[1] != i && arr[2] != i) continue;
                auto c = arr[1] ^ i ^ arr[2];
                if (curr + arr[0] - maxi[c] == curr) s.emplace(arr);
                if (curr + arr[0] - maxi[c] > x) cnt++;
            }
        }
        int q = s.size() + (m - w.size());
        int p = m - q;
        cout << (modpow(2, q) + mod - 2) % mod * modpow(2, p) % mod << "\n";
    }
    return 0;
}

Measured memory_bytes: 512