// 基本テンプレート
 
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
using namespace std;
 
#define rep(i,a,n) for(int (i)=(a); (i)<(n); (i)++)
#define repq(i,a,n) for(int (i)=(a); (i)<=(n); (i)++)
#define repr(i,a,n) for(int (i)=(a); (i)>=(n); (i)--)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define int long long int
 
template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}
 
typedef pair<int, int> pii;
typedef long long ll;
 
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const ll INF = 1001001001001001LL;
const ll MOD = 1000000007LL;

// Union-Find 木 (Verified: AtCoder Typical Contest 001 B)
struct UnionFind {
private:
    const int n;
    int __size;
    vector<int> uf;
public:
    // 初期化 UnionFind uni(n) のように宣言すれば良い
    UnionFind(int _n) : n(_n), __size(_n), uf(_n, -1) {}
    // find (木の根を求める)
    int find(int x) {return (uf[x] < 0) ? x : uf[x] = find(uf[x]);}
    // x と y が同じ集合に属するかどうか
    bool same(int x, int y) {return find(x) == find(y);}
    // x が属する集合の要素数
    int size(int x) {return -uf[find(x)];}
    // 集合はいくつあるか
    int size()      {return __size;}
    // x と y の属する集合を併合
    void unite(int x, int y) {
        x = find(x); y = find(y);
        if(x == y) return;
        __size--;
        if(uf[y] < uf[x]) swap(x, y);
        uf[x] += uf[y]; uf[y] = x;
    }
};

int mod_pow(int N, int K) {
    int ret = 1;
    for(; K>0; K>>=1) {
        if(K & 1) (ret *= N) %= MOD;
        (N *= N) %= MOD;
    }
    return ret;
}

struct Edge {
    int from, to, cost;
    Edge(int f, int t, int c) : from(f), to(t), cost(c) {}
    Edge(int t, int c) : to(t), cost(c) {}
    bool operator<(const Edge &e) const {
        return cost < e.cost;
    }
};

int N, M, X;

using Graph = vector< vector<Edge> >;
int get_cost(Graph &G, int u, int v) {
    vector<int> rec(N, -1);
    queue<int> que;
    que.push(u);
    while(que.size()) {
        int cur = que.front(); que.pop();
        for(auto e : G[cur]) {
            int to = e.to;
            if(rec[to] != -1) continue;
            rec[to] = max(e.cost, rec[cur]);
            if(to == v) return rec[to];
            que.push(to);
        }
    }
    return -1;
}
 
signed main() {
    scanf("%lld%lld%lld", &N, &M, &X);

    vector<Edge> edges;
    vector<int> used(M);
    for(int i=0; i<M; i++) {
        int u, v, d; scanf("%lld%lld%lld", &u, &v, &d);
        u--; v--;
        edges.push_back(Edge(u, v, d));
    }
    sort(edges.begin(), edges.end());

    UnionFind uf(N);
    int sum = 0;
    Graph G(N);
    for(int i=0; i<M; i++) {
        Edge e = edges[i];
        if(uf.same(e.from, e.to) == false) {
            // printf("use: (%lld, %lld, cost = %lld)\n", e.from, e.to, e.cost);
            used[i] = true;
            uf.unite(e.from, e.to);
            sum += e.cost;
            G[e.from].push_back(Edge(e.to, e.cost));
            G[e.to].push_back(Edge(e.from, e.cost));
        }
    }

    int diff = X - sum, ans = 0;
    // printf("diff = %lld\n", diff);
    int less = 0, equal = 0, more = 0;
    for(int i=0; i<M; i++) {
        if(used[i]) continue;
        int u = edges[i].from, v = edges[i].to;
        int val = edges[i].cost - get_cost(G, u, v);
        // printf("u = %lld, v = %lld, get_cost = %lld\n", u, v, get_cost(G, u, v));
        if(val  < diff) less++;
        if(val == diff) equal++;
        if(val  > diff) more++;
    }

    if(diff >= 0) {
        // printf("less = %lld, equal = %lld, more = %lld\n", less, equal, more);
        int orig_mst = (mod_pow(2, N-1) - 2 + MOD) % MOD * mod_pow(2, M-N+1) % MOD;
        int use_equal = 2 * (mod_pow(2, equal) - 1 + MOD) % MOD * mod_pow(2, more) % MOD;
        if(diff == 0) (ans += orig_mst) %= MOD;
        (ans += use_equal) %= MOD;
    }
    printf("%lld\n", ans);
    return 0;
}

Measured memory_bytes: 384