#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<ll, ll> P;

#define each(i,a) for (auto&& i : a)
#define FOR(i,a,b) for (ll i=(a),__last_##i=(b);i<__last_##i;i++)
#define RFOR(i,a,b) for (ll i=(b)-1,__last_##i=(a);i>=__last_##i;i--)
#define REP(i,n) FOR(i,0,n)
#define RREP(i,n) RFOR(i,0,n)
#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME
#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)
#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define chmin(x,v) x = min(x, v)
#define chmax(x,v) x = max(x, v)

const ll linf = 1e18;
const double eps = 1e-12;
const double pi = acos(-1);

template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
    each(x,vec) is >> x;
    return is;
}
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& vec) {
    rep(i,vec.size()) {
        if (i) os << " ";
        os << vec[i];
    }
    return os;
}
template<typename T>
ostream& operator<<(ostream& os, const vector< vector<T> >& vec) {
    rep(i,vec.size()) {
        if (i) os << endl;
        os << vec[i];
    }
    return os;
}
class UnionFind {
    vector<ll> par, h, sz;
public:
    UnionFind(ll size) : par(size, 0), h(size, 0), sz(size, 1) {
        rep(i, size) par[i] = i;
    }
    void unite(ll u, ll v) {
        u = root(u), v = root(v);
        if (u == v) return;
        if (h[u] < h[v]) {
            par[u] = v;
            sz[v] += sz[u];
        }
        else {
            par[v] = u;
            sz[u] += sz[v];
        }
        if (h[u] == h[v]) ++h[u];
    }
    ll size(ll v) {
        return sz[root(v)];
    }
    bool isUnited(ll u, ll v) {
        return root(u) == root(v);
    }
    ll root(ll v) {
        if (par[v] == v) return v;
        return par[v] = root(par[v]);
    }
};
struct Edge {
    ll a, b, c;
};
bool operator<(const Edge& e1, const Edge& e2) {
    return e1.c < e2.c;
}
class WeightedTree {
    const ll id = 0;
    ll merge(ll a, ll b) {
        return a + b;
    }
    ll expand(ll x) {
        ll res = 0;
        while ((1LL<<res) < x) ++res;
        return res;
    }
    void prepare_lca() {
        if (par.size() == 0) dfs();
        par2.assign(expand(n)+1, vector<ll>(par.size()));
        cost.assign(par2.size(), vector<ll>(par.size(), id));
        rep(i, n) {
            par2[0][i] = par[i].to;
            cost[0][i] = par[i].cost;
        }
        rep(i, 1, par2.size()) {
            rep(j, n) {
                if (par2[i-1][j] < 0) {
                    par2[i][j] = par2[i-1][j];
                    cost[i][j] = cost[i-1][j];
                }
                else {
                    par2[i][j] = par2[i-1][par2[i-1][j]];
                    cost[i][j] = merge(cost[i-1][j], cost[i-1][par2[i-1][j]]);
                }
            }
        }
    }
    void dfs(ll v, ll pv, ll d) {
        depth[v] = d;
        size[v] = 1;
        each(e, G[v]) {
            if (e.to == pv) continue;
            chs[v].pb(e);
            par[e.to] = {v, e.cost};
            dfs(e.to, v, d+1);
            size[v] += size[e.to];
        }
    }
public:
    struct Edge {
        ll to, cost;
    };
    ll n;
    vector<vector<Edge>> G, chs;
    vector<Edge> par;
    vector<ll> depth, size;
    vector<vector<ll>> par2;
    vector<vector<ll>> cost;
    WeightedTree(ll sz) : n(sz), G(sz) {
    }
    void add(ll u, ll v, ll c) {
        G[u].pb({v, c});
        G[v].pb({u, c});
    }
    void dfs() {
        par.assign(n, {-1, id});
        chs.clear(); chs.resize(n);
        size.assign(n, 0);
        depth.assign(n, 0);
        dfs(0, -1, 0);
    }
    P lca(ll u, ll v) {
        if (par2.size() == 0) prepare_lca();
        if (depth[u] > depth[v]) swap(u, v);
        ll res = id;
        rrep(i, par2.size()) {
            if ((depth[v] - depth[u]) & (1LL<<i)) {
                res = merge(res, cost[i][v]);
                v = par2[i][v];
            }
        }
        assert(depth[u] == depth[v]);
        if (u == v) return {u, res};
        rrep(i, par2.size()) {
            if (par2[i][u] != par2[i][v]) {
                res = merge(res, cost[i][u]);
                res = merge(res, cost[i][v]);
                u = par2[i][u];
                v = par2[i][v];
            }
        }
        assert(par[u].to == par[v].to && par[u].to >= 0);
        return {par[u].to, res};
    }
};
const ll mod = 1e9+7;
ll mul(ll a, ll b) {
    return a * b % mod;
}
ll mul(initializer_list<ll> t) {
    ll res = 1;
    each(v, t) res = mul(res, v);
    return res;
}
ll add(ll a, ll b) {
    return (a + b) % mod;
}
ll add(initializer_list<ll> t) {
    ll res = 0;
    each(v, t) res = add(res, v);
    return res;
}
ll sub(ll a, ll b) {
    return (a - b + mod) % mod;
}
ll sub(initializer_list<ll> t) {
    auto it = t.begin();
    ll res = *(it++);
    while (it != t.end()) {
        res = sub(res, *(it++));
    }
    return res;
}
ll power(ll x, ll n) {
    ll res = 1;
    for (ll i = 1; i <= n; i <<= 1) {
        if (i & n) res = mul(res, x);
        x = mul(x, x);
    }
    return res;
}
ll inv(ll n) {
    return power(n, mod-2);
}
ll divi(ll a, ll b) {
    return mul(a, inv(b));
}
ll divi(initializer_list<ll> t) {
    auto it = t.begin();
    ll res = *(it++);
    while (it != t.end()) {
        res = divi(res, *(it++));
    }
    return res;
}
vector<ll> fact;
void init_fact(ll n) {
    fact.assign(n+1, 1);
    FOR(i, 1, fact.size()) {
        fact[i] = mul(fact[i-1], i);
    }
}

ll comb(ll n, ll r) {
    if (r < 0) return 0;
    if (r > n) return 0;
    return divi(fact[n], mul(fact[r], fact[n-r]));
}

using Row = vector<ll>;
using Matrix = vector<Row>;
Matrix E(ll n) {
    Matrix res(n, Row(n, 0));
    rep(i, n) res[i][i] = 1;
    return res;
}
Matrix mul(const Matrix& A, const Matrix& B) {
    const ll n = A.size(), m = A[0].size(), l = B[0].size();
    assert(m == B.size());
    Matrix res(n, Row(l, 0));
    rep(i, n) rep(j, m) rep(k, l) {
        res[i][k] = add(res[i][k], mul(A[i][j], B[j][k]));
    }
    return res;
}
Matrix power(Matrix A, ll n) {
    assert(A.size() == A[0].size());
    Matrix res = E(A.size());
    for (ll i = 1; i <= n; i <<= 1) {
        if (i & n) res = mul(res, A);
        A = mul(A, A);
    }
    return res;
}
void gen_fact_result(ll d, ll num) {
    ll x = 1;
    cout << "#define FACT";
    cout << "vector<P> facts = {";
    rep(i, d*(num-1)+1) {
        if (i % d == 0) {
            cout << "{" << i << "," << x << "},";
        }
        x = mul(x, i+1);
    }
    cout << "};";
}
#define FACT
vector<P> facts = {{0,1},{10000000,682498929},{20000000,491101308},{30000000,76479948},{40000000,723816384},{50000000,67347853},{60000000,27368307},{70000000,625544428},{80000000,199888908},{90000000,888050723},{100000000,927880474},{110000000,281863274},{120000000,661224977},{130000000,623534362},{140000000,970055531},{150000000,261384175},{160000000,195888993},{170000000,66404266},{180000000,547665832},{190000000,109838563},{200000000,933245637},{210000000,724691727},{220000000,368925948},{230000000,268838846},{240000000,136026497},{250000000,112390913},{260000000,135498044},{270000000,217544623},{280000000,419363534},{290000000,500780548},{300000000,668123525},{310000000,128487469},{320000000,30977140},{330000000,522049725},{340000000,309058615},{350000000,386027524},{360000000,189239124},{370000000,148528617},{380000000,940567523},{390000000,917084264},{400000000,429277690},{410000000,996164327},{420000000,358655417},{430000000,568392357},{440000000,780072518},{450000000,462639908},{460000000,275105629},{470000000,909210595},{480000000,99199382},{490000000,703397904},{500000000,733333339},{510000000,97830135},{520000000,608823837},{530000000,256141983},{540000000,141827977},{550000000,696628828},{560000000,637939935},{570000000,811575797},{580000000,848924691},{590000000,131772368},{600000000,724464507},{610000000,272814771},{620000000,326159309},{630000000,456152084},{640000000,903466878},{650000000,92255682},{660000000,769795511},{670000000,373745190},{680000000,606241871},{690000000,825871994},{700000000,957939114},{710000000,435887178},{720000000,852304035},{730000000,663307737},{740000000,375297772},{750000000,217598709},{760000000,624148346},{770000000,671734977},{780000000,624500515},{790000000,748510389},{800000000,203191898},{810000000,423951674},{820000000,629786193},{830000000,672850561},{840000000,814362881},{850000000,823845496},{860000000,116667533},{870000000,256473217},{880000000,627655552},{890000000,245795606},{900000000,586445753},{910000000,172114298},{920000000,193781724},{930000000,778983779},{940000000,83868974},{950000000,315103615},{960000000,965785236},{970000000,492741665},{980000000,377329025},{990000000,847549272},};
#ifdef FACT
ll bigfact(ll n) {
    if (n >= mod) return 0;
    auto it = upper_bound(all(facts), P(n, linf));
    assert(it != facts.begin());
    --it;
    ll s = it->first;
    ll res = it->second;
    rep(i, s+1, n+1) {
        res = mul(res, i);
    }
    return res;
}
#endif

pair<ll, WeightedTree> mst(const ll n, vector<Edge> edges, const Edge& e0) {
    sort(all(edges));
    UnionFind uf(n);
    ll cost = e0.c;
    uf.unite(e0.a, e0.b);
    WeightedTree t(n);
    each(e, edges) {
        if (uf.isUnited(e.a, e.b)) continue;
        uf.unite(e.a, e.b);
        cost += e.c;
        t.add(e.a, e.b, e.c);
    }
    return pair<ll, WeightedTree>{cost, t};
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll n, m; cin >> n >> m;
    ll X; cin >> X;
    vector<Edge> edges;
    rep(i, m) {
        ll a, b, c; cin >> a >> b >> c; --a, --b;
        edges.pb({a, b, c});
    }
    vector<pair<ll, WeightedTree>> results;
    rep(i, m) {
        results.pb(mst(n, edges, edges[i]));
    }
    auto result = mst(n, edges, {0, 0, 0});
    map<P, ll> eid;
    rep(i, m) {
        eid[P(edges[i].a, edges[i].b)] = i;
        eid[P(edges[i].b, edges[i].a)] = i;
    }
    WeightedTree& T = result.second;
    vector<bool> used(m, false);
    rep(v, n) each(e, T.G[v]) {
        used[eid[P(v, e.to)]] = true;
    }
    if (result.first == X) {
        ll ans = power(2, m);
        // ans = sub(ans, mul(2, power(2, m-(n-1))));
        ll cnt = 0;
        rep(i, m) {
            if (used[i]) continue;
            if (results[i].first == X) ++cnt;
        }
        ans = sub(ans, mul(2, power(2, m - (n-1) - cnt)));
        cout << ans << endl;
    }
    else {
        ll cnt1 = 0, cnt2 = 0;
        rep(i, m) {
            if (used[i]) continue;
            if (results[i].first < X) {
                ++cnt1;
            }
            if (results[i].first == X) ++cnt2;
        }
        ll X = cnt2;
        ll Y = m - (n-1) - cnt1 - cnt2;
        ll ans = power(2, X + Y);
        ans = sub(ans, power(2, Y));
        ans = mul(ans, 2);
        cout << ans << endl;
    }
}


Measured memory_bytes: 142012