#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 1010, M = 2010, LOG = 21;
const ll inf = 0x3f3f3f3f3f3f3f3fll;

int n, m;
ll X;
struct edge {
    int u, v;
    ll w;
    edge(int _u = 0, int _v = 0, ll _w = 0) : u(_u), v(_v), w(_w) { }
    bool operator<(const edge &o) const { return w < o.w; }
} edges[M];

vector<edge> g[N];
void addedge(int u, int v, ll w) {
    g[u].emplace_back(u, v, w);
    g[v].emplace_back(v, u, w);
}

int anc[N][LOG], depth[N];
ll mx[N][LOG];

void dfs(int u, int f = 0, ll lstw = -inf) {
    anc[u][0] = f;
    mx[u][0] = lstw;
    depth[u] = depth[f] + 1;
    for (int i = 1; i < LOG; ++i) {
        anc[u][i] = anc[anc[u][i - 1]][i - 1];
        mx[u][i] = max(mx[u][i - 1], mx[anc[u][i - 1]][i - 1]);
    }
    for (auto e : g[u]) {
        int v = e.v;
        ll w = e.w;
        if (v == f) continue;
        dfs(v, u, w);
    }
}

int lca(int u, int v) {
    if (depth[u] < depth[v]) swap(u, v);
    for (int i = LOG - 1; i >= 0; --i)
        if (depth[anc[u][i]] >= depth[v]) u = anc[u][i];
    if (u == v) return u;
    for (int i = LOG - 1; i >= 0; --i)
        if (anc[u][i] != anc[v][i]) {
            u = anc[u][i];
            v = anc[v][i];
        }
    return anc[u][0];
}
ll query(int u, int v) {
    ll ans = -inf;
    if (depth[u] < depth[v]) swap(u, v);
    for (int i = LOG - 1; i >= 0; --i)
        if (depth[anc[u][i]] >= depth[v]) {
            ans = max(ans, mx[u][i]);
            u = anc[u][i];
        }
    if (u == v) return ans;
    for (int i = LOG - 1; i >= 0; --i)
        if (anc[u][i] != anc[v][i]) {
            ans = max(ans, max(mx[u][i], mx[v][i]));
            u = anc[u][i];
            v = anc[v][i];
        }
    ans = max(ans, max(mx[u][0], mx[v][0]));
    return ans;
}

int fa[N];
int find(int u) {
    return u == fa[u] ? u : fa[u] = find(fa[u]);
}

const int P = 1e9 + 7;
inline int mpow(int a, int b) {
    int ans = 1;
    for (; b; b >>= 1, a = (ll) a * a % P)
        if (b & 1) ans = (ll) ans * a % P;
    return ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m >> X;
    for (int i = 1; i <= m; ++i) {
        int u, v;
        ll w;
        cin >> u >> v >> w;
        edges[i] = {u, v, w};
    }
    for (int i = 1; i <= n; ++i)
        fa[i] = i;
    sort(edges + 1, edges + m + 1);
    vector<bool> in(m + 1);
    ll mst = 0;
    for (int i = 1; i <= m; ++i) {
        int u = edges[i].u, v = edges[i].v;
        ll w = edges[i].w;
        int pu = find(u), pv = find(v);
        if (pu == pv) in[i] = false;
        else {
            addedge(u, v, w);
            fa[pu] = pv;
            in[i] = true;
            mst += w;
        }
    }
    dfs(1);
    // cerr << mst << '\n';
    if (mst > X) {
        cout << "0\n";
        return 0;
    }
    if (mst == X) {
        int tot = 0;
        for (int i = 1; i <= m; ++i) {
            if (!in[i]) {
                int u = edges[i].u, v = edges[i].v, w = edges[i].w;
                in[i] = query(u, v) == w;
            }
            tot += in[i];
        }
        cout << (ll) mpow(2, m - tot) * (mpow(2, tot) - 2ll + P) % P;
    } else {
        int c1 = 0, c2 = 0;
        for (int i = 1; i <= m; ++i) if (!in[i]) {
            int u = edges[i].u, v = edges[i].v, w = edges[i].w;
            int delta = w - query(u, v);
            if (mst + delta == X) {
                ++c1;
            }
            if (mst + delta > X) {
                ++c2;
            }
        }
        cout << (ll) 2 * (mpow(2, c1) - 1 + P) % P * mpow(2, c2) % P << '\n';
    }
    return 0;
}

Measured memory_bytes: 4020