#include <bits/stdc++.h>

using namespace std;

constexpr int MOD = 1000000007;

using Long = long long;
template<typename T>
using V = vector<T>;
template<typename T>
using Vv = V<V<T>>;
using Vb = V<bool>;
using Vvb = V<Vb>;
using Vi = V<int>;
using Vvi = V<Vi>;
using Vl = V<Long>;
using Vvl = V<Vl>;
using Vd = V<double>;
using Vvd = V<Vd>;
using Vs = V<string>;

template <typename T>
istream& operator>>(istream& is, vector<T>& v) {
    for (auto& x : v) {
        is >> x;
    }
    return is;
}

template <typename First, typename Second>
istream& operator>>(istream& is, pair<First, Second>& x) {
    return is >> x.first >> x.second;
}

class UnionFind {
public:
    explicit UnionFind(int size) : data(size, -1), numUnions{size} {}

    int getNumUnions() {
        return numUnions;
    }

    int getUnionSize(int u) {
        return -data[find(u)];
    }

    bool isUnited(int u, int v) {
        return find(u) == find(v);
    }

    struct UniteResult {
        int root;
        bool united;
    };

    UniteResult unite(int u, int v) {
        int uRoot = find(u);
        int vRoot = find(v);
        if (uRoot == vRoot) {
            return {uRoot, false};
        }
        int uSize = data[uRoot];
        int vSize = data[vRoot];
        if (uSize > vSize) {
            swap(uRoot, vRoot);
            swap(uSize, vSize);
        }
        data[uRoot] += vSize;
        data[vRoot] = uRoot;
        numUnions--;
        return {uRoot, true};
    }

    int find(int u) {
        assert(u >= 0 && u < data.size());
        int p = data[u];
        if (p < 0) {
            return u;
        }
        int gp = data[p];
        if (gp < 0) {
            return p;
        }
        data[u] = gp;
        return find(gp);
    }

private:
    vector<int> data;
    int numUnions;
};

// *** SOLUTION BEGIN ***

void solve() {
    int n, m;
    Long x;
    cin >> n >> m >> x;
    vector<pair<int, pair<int, int>>> edges(m);
    for (auto& e : edges) {
        cin >> e.second >> e.first;
        e.second.first--;
        e.second.second--;
    }
    sort(begin(edges), end(edges));
    int countLess = 0;
    int countEqual = 0;
    int countGreater = 0;
    for (const auto& e : edges) {
        UnionFind uf{n};
        uf.unite(e.second.first, e.second.second);
        Long w = e.first;
        for (const auto& ee : edges) {
            if (uf.unite(ee.second.first, ee.second.second).united) {
                w += ee.first;
            }
        }
        if (w < x) {
            countLess++;
        } else if (w == x) {
            countEqual++;
        } else {
            countGreater++;
        }
    }
    auto pow = [](int x, int y) {
        Long res = 1;
        while (y--) {
            res *= x;
            res %= MOD;
        }
        return res;
    };
    if (countLess) {
        cout << 2 * (pow(2, countEqual) + MOD - 1LL) * pow(2, countGreater) % MOD;
    } else if (countEqual) {
        cout << (pow(2, countEqual) + MOD - 2LL) * pow(2, countGreater) % MOD;
    } else {
        cout << 0;
    }
}

// *** SOLUTION END ***

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    cout.precision(10);
    cout << fixed;
    solve();
    return 0;
}


Measured memory_bytes: 256