// Original C++ solution (slower):
#include <bits/stdc++.h>



using namespace std;



const int max_n = 2022, mod = 1000000007;



struct edge {

    int u, v, d;



    bool operator < (const edge &e) const {

        return d < e.d;

    }

};



int mul(int x, int y) {

    return 1LL * x * y % mod;

}



int n, m, p[max_n], pw[max_n];

edge e[max_n];

bool take[max_n];

vector<int> g[max_n], d[max_n];

long long x;



int find_set(int v) {

    if (v == p[v]) {

        return v;

    }

    return p[v] = find_set(p[v]);

}



bool union_set(int v1, int v2) {

    v1 = find_set(v1);

    v2 = find_set(v2);

    if (v1 == v2) {

        return false;

    }

    p[v1] = v2;

    return true;

}



int get_max(int v, int fin, int mx, int p) {

    if (v == fin) {

        return mx;

    }

    int res = -1;

    for (int i = 0; i < g[v].size(); ++i) {

        const int to = g[v][i], c = d[v][i];

        if (to == p) {

            continue;

        }

        res = max(res, get_max(to, fin, max(mx, c), v));

    }

    return res;

}



int main() {

    //freopen("input.txt", "r", stdin);

    //freopen("output.txt", "w", stdout);

    pw[0] = 1;

    for (int i = 1; i < max_n; ++i) {

        pw[i] = mul(pw[i - 1], 2);

    }

    cin >> n >> m >> x;

    if (n <= 2) {

        cout << 0 << endl;

        return 0;

    }

    for (int i = 0; i < m; ++i) {

        cin >> e[i].u >> e[i].v >> e[i].d;

        --e[i].u;

        --e[i].v;

    }

    sort(e, e + m);

    for (int i = 0; i < n; ++i) {

        p[i] = i;

    }

    long long tot = 0;

    for (int i = 0; i < m; ++i) {

        take[i] = false;

        if (union_set(e[i].u, e[i].v)) {

            take[i] = true;

            tot += e[i].d;

            g[e[i].u].push_back(e[i].v);

            d[e[i].u].push_back(e[i].d);

            g[e[i].v].push_back(e[i].u);

            d[e[i].v].push_back(e[i].d);

        }

    }

    int ans = 0;

    if (tot == x) {

        ans += mul(pw[n - 1] + mod - 2, pw[m - n + 1]);

    }

    vector<int> all;

    for (int i = 0; i < m; ++i) {

        if (!take[i]) {

            int mx = get_max(e[i].u, e[i].v, -1, -1);

            all.push_back(e[i].d - mx);

        }

    }

    sort(all.begin(), all.end());

    for (int i = 0; i < all.size(); ++i) {

        if (tot + all[i] == x) {

            ans += pw[all.size() - i];

            ans %= mod;

        }

    }

    cout << ans << endl;

    return 0;

}


// Optimized solution to the same problem (faster):
#include<algorithm> 

#include<cstdio>

#include<iostream>

#define inver(a) power(a,mod-2)

using namespace std;

typedef long long LL;

const int mod=1e9+7;

int fac[2050];

int fac_inv[2050];

int add(int x)

{

	return x>=mod?x-mod:x; 

}

LL power(LL x,LL y)

{

	LL re=1;

	while(y)

	{

		if(y&1) re=re*x%mod;

		x=x*x%mod;

		y>>=1;

	}

	return re;

}

LL C(int x,int y)

{

	return (LL)fac[x]*fac_inv[y]%mod*fac_inv[x-y]%mod;

}

int n,m;

int p2[2050];

bool mark[2050];

LL X;

LL v[2050];

namespace us

{

	int fa[1050];

	void init()

	{

		for(int i=1;i<=n;++i)

		{

			fa[i]=i;

		}

	}

	int find(int a)

	{

		return fa[a]==a?a:fa[a]=find(fa[a]); 

	}

	bool merge(int a,int b)

	{

		a=find(a);

		b=find(b);

		if(a==b)

		{

			return false;

		}

		fa[a]=b;

		return true;

	}

}

struct edge

{

	int u,v,w;

	bool operator <(const edge &other) const

	{

		return w<other.w;

	}

} e[2050];

LL kruskal(int ban)

{

	LL MST=0;

	us::init();

	if(ban)

	{

		us::merge(e[ban].u,e[ban].v);

		MST+=e[ban].w;

	}

	for(int i=1;i<=m;++i)if(i!=ban)

	{

		if(us::merge(e[i].u,e[i].v))

		{

			MST+=e[i].w;

			if(ban==0)

			{

				mark[i]=1;

			}

		}

	}

	return MST;

}

void init(int n)

{

	p2[0]=1;

	for(int i=1;i<=n;++i)

	{

		p2[i]=add(p2[i-1]<<1);

	}

	fac[0]=1;

	for(int i=1;i<=n;++i)

	{

		fac[i]=(LL)fac[i-1]*i%mod;

	}

	fac_inv[n]=inver(fac[n]);

	for(int i=n;i>=1;--i)

	{

		fac_inv[i-1]=(LL)fac_inv[i]*i%mod;

	} 

}

int calc()

{

	int p=n-1;

	int re=0;

	for(int i=1;i<p;++i)

	{

		re=add(re+C(p,i));

	}

	re=(LL)re*p2[m-p]%mod;

	return re;

}

int solve()

{

	init(m);

	for(int i=0;i<=m;++i)

	{

		v[i]=kruskal(i);

	}

	int an=0;

	if(v[0]==X)

	{

		an=calc();

	}

	for(int i=1;i<=m;++i) if(!mark[i])

	{

		if(v[i]==X)

		{

			int t=1;

			for(int j=1;j<=m;++j) if(!mark[j])

			{

				if(v[j]>v[i]||(v[j]==v[i]&&j>i))

				{

					++t;

				}

			}

			an=add(an+p2[t]);

		}

	}

	return an;

}

int main()

{

	scanf("%d%d",&n,&m);

	scanf("%lld",&X);

	for(int i=1;i<=m;++i)

	{

		scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);

	}

	sort(e+1,e+m+1);

	printf("%d\n",solve());

	return 0;

}

// Fastest known solution for this problem: