#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr ll MOD = 1000000007LL;
template <typename T>
constexpr T INF = numeric_limits<T>::max() / 10;

class DisjointSets
{
public:
    DisjointSets(const int v) : parent(v), rank(v, 0) { iota(parent.begin(), parent.end(), 0); }
    bool same(const int a, const int b) { return find(a) == find(b); }
    int find(const int a) { return parent[a] == a ? a : parent[a] = find(parent[a]); }
    void unite(int a, int b)
    {
        a = find(a);
        b = find(b);
        if (a == b) {
            return;
        }
        if (rank[a] < rank[b]) {
            swap(a, b);
        }
        rank[a] += rank[b];
        parent[b] = a;
    }

private:
    vector<int> parent;
    vector<int> rank;
};

struct Edge
{
    bool operator<(const Edge& e) const { return cost < e.cost; }
    int from;
    int to;
    ll cost;
};

struct CostGraph
{
    using T = ll;
    CostGraph(const int v) : edge(v) {}
    struct Edge
    {
        Edge(const int from, const int to, const T cost) : from{from}, to{to}, cost{cost} {}
        const int from;
        const int to;
        const T cost;
    };
    void addEdge(const int from, const int to, const T cost) { edge[from].push_back(Edge{from, to, cost}); }
    vector<vector<Edge>> edge;
};

ll rec(const CostGraph& g, const int s, const int t, const ll mini, const int prev)
{
    if (s == t) return mini;
    ll ans = -INF<ll>;
    for (const auto& e : g.edge[s]) {
        if (prev != e.to) ans = max(ans, rec(g, e.to, t, max(mini, e.cost), s));
    }
    return ans;
}
// u-vパス上の最大重み
ll cut(const CostGraph& g, const int s, const int t) { return rec(g, s, t, -INF<ll>, -1); }
ll power(const ll n)
{
    if (n == 0) {
        return 1;
    }
    if (n % 2 == 1) {
        return power(n - 1) * 2 % MOD;
    } else {
        const ll pp = power(n / 2);
        return pp * pp % MOD;
    }
}
int main()
{
    int N, M;
    ll X;
    cin >> N >> M >> X;
    DisjointSets uf(N);
    vector<Edge> edge(M);
    for (int i = 0; i < M; i++) {
        int u, v;
        ll w;
        cin >> u >> v >> w;
        u--, v--;
        edge[i] = {u, v, w};
    }
    sort(edge.begin(), edge.end());
    int n2 = 0;  // Xと等しい重みのBSTに必要な辺の本数
    int n3 = 0;  // どうでも良い辺
    ll mst = 0;
    vector<bool> used(M, false);  // MSTに使われているか
    CostGraph g(N);
    for (int i = 0; i < M; i++) {
        const int u = edge[i].from;
        const int v = edge[i].to;
        const ll w = edge[i].cost;
        if (not uf.same(u, v)) {
            mst += w;
            uf.unite(u, v);
            g.addEdge(u, v, w);
            g.addEdge(v, u, w);
            used[i] = true;
        }
    }
    for (int i = 0; i < M; i++) {
        if (not used[i]) {
            const int u = edge[i].from;
            const int v = edge[i].to;
            const ll w = edge[i].cost;
            const ll maxcut = cut(g, u, v);
            const ll next = mst - maxcut + w;
            if (next == X) {
                n2++;
            } else if (next > X) {
                n3++;
            }
        }
    }
    ll ans = (X == mst ? (power(N - 1) + MOD - 2) * power(M - N + 1) % MOD : 0);
    (ans += (2 * (power(n2) + MOD - 1) % MOD) * power(n3) % MOD) %= MOD;
    cout << ans << endl;
    return 0;
}


Measured memory_bytes: 512