#include<bits/stdc++.h>
#define ll long long
#define db double
#define lowbit(p) (p&(-p))
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define A first
#define B second
using namespace std;
void read(int &x){
	x=0; char c=getchar(); int p=1;
	for (;c<48;c=getchar())if (c=='-')p=-1;
	for (;c>47;c=getchar())x=(x<<1)+(x<<3)+(c^48);
	x*=p;
}
void read(ll &x){
	x=0; char c=getchar(); int p=1;
	for (;c<48;c=getchar())if (c=='-')p=-1;
	for (;c>47;c=getchar())x=(x<<1)+(x<<3)+(c^48);
	x*=p;
}
void Min(int &x,int y){
	if (x>y)x=y;
}
void Max(int &x,int y){
	if (x<y)x=y;
}
void Min(ll &x,ll y){
	if (x>y)x=y;
}
void Max(ll &x,ll y){
	if (x<y)x=y;
}
#define mo 1000000007
#define M 4005
ll ksm(ll a,ll b){
	ll res=1;
	for (;b;b>>=1){
		if (b&1)res=res*a%mo;
		a=a*a%mo;
	}
	return res;
}
int n,m;
ll val,sum,len[M];
int top[M],cnt[M],son[M],de[M],L[M],tot,fa[M],id[M];
struct edg{
	int x,y;
	ll l;
	void init(){
		read(x); read(y); read(l);
	}
}edge[M];
bool cmp(edg a,edg b){
	return a.l<b.l;
}
struct ed{
	int x;
	ll l;
	int nx;
}e[M];
int nx[M],ecnt=1;
bool mark[M];
int get(int x){
	if (fa[x]==x)return x;
	return fa[x]=get(fa[x]);
}
void add(int x,int y,ll l){
	e[ecnt]=(ed){y,l,nx[x]};
	nx[x]=ecnt++;
}
void ins(int x,int y,ll l){
	add(x,y,l);
	add(y,x,l);
}
struct Reimu{
	ll f[M<<2];
	#define ls (p<<1)
	#define rs (p<<1|1)
	void build(int l,int r,int p){
		if (l==r){
			f[p]=len[id[l]];
			return;
		}
		int mid=(l+r)>>1;
		build(l,mid,ls);
		build(mid+1,r,rs);
		f[p]=max(f[ls],f[rs]);
	}
	ll qu(int l,int r,int x,int y,int p){
		if (l==x&&r==y){
			return f[p];
		}
		int mid=(l+r)>>1;
		if (y<=mid)return qu(l,mid,x,y,ls);
		if (x>mid)return qu(mid+1,r,x,y,rs);
		return max(qu(l,mid,x,mid,ls),qu(mid+1,r,mid+1,y,rs));
	}
}T;
void dfs1(int f,int x){
	cnt[x]=1; de[x]=de[f]+1; fa[x]=f;
	for (int i=nx[x];i;i=e[i].nx)if (e[i].x!=f){
		len[e[i].x]=e[i].l;
		dfs1(x,e[i].x);
		cnt[x]+=cnt[e[i].x];
		if (cnt[e[i].x]>cnt[son[x]]){
			son[x]=e[i].x;
		}
	}
}
void dfs2(int f,int x){
	L[x]=++tot; top[x]=f; id[tot]=x;
	if (son[x]){
		dfs2(f,son[x]);
		for (int i=nx[x];i;i=e[i].nx)if (e[i].x!=fa[x]&&e[i].x!=son[x]){
			dfs2(e[i].x,e[i].x);
		}
	}
}
ll chk(edg e){
	int x=e.x,y=e.y;
	ll res=0;
	for (;top[x]!=top[y];){
		if (de[top[x]]>de[top[y]]){
			Max(res,T.qu(1,n,L[top[x]],L[x],1));
			x=fa[top[x]];
		}
		else {
			Max(res,T.qu(1,n,L[top[y]],L[y],1));
			y=fa[top[y]];
		}
	}
	if (de[x]<de[y]){
		if (L[x]<L[y])Max(res,T.qu(1,n,L[x]+1,L[y],1));
	}
	else {
		if (L[y]<L[x])Max(res,T.qu(1,n,L[y]+1,L[x],1));
	}
	return sum+e.l-res;
}
struct P1{
	void solve(){
		int i,tot=0;
		ll res;
		for (i=1;i<=m;i++){
			if (chk(edge[i])==val){
				tot++;
			}
		}
		res=ksm(2,m-tot)*(ksm(2,tot)-2)%mo;
		res=(res+mo)%mo;
		printf("%lld\n",res);
	}
}p1;
struct P2{
	void solve(){
		int i,tot1=0,tot2=0;
		ll res,tmp;
		for (i=1;i<=m;i++){
			tmp=chk(edge[i]);
//			printf("%d %d   %lld  %lld\n",edge[i].x,edge[i].y,edge[i].l,tmp);
			if (tmp==val){
				tot2++;
			}
			else if (tmp>val){
				tot1++;
			}
		}
//		printf("tot1=%d tot2=%d\n",tot1,tot2);
		res=2ll*ksm(2,tot1)%mo*(ksm(2,tot2)-1)%mo;
		res=(res+mo)%mo;
		printf("%lld\n",res);
	}
}p2;
int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	freopen("1.in","r",stdin);
	read(n); read(m);
	read(val);
//	printf("val=%lld\n",val);
	int i,x,y;
	for (i=1;i<=m;i++){
		edge[i].init();
	}
	for (i=1;i<=n;i++){
		fa[i]=i;
	}
	sort(edge+1,edge+m+1,cmp);
	for (i=1;i<=m;i++){
		x=get(edge[i].x);
		y=get(edge[i].y);
		if (x!=y){
			fa[x]=y;
			sum+=edge[i].l;
			mark[i]=1;
		}
	}
	if (sum>val){
		printf("0\n");
		return 0;
	}
	else {
		for (i=1;i<=m;i++){
			if (mark[i]){
				ins(edge[i].x,edge[i].y,edge[i].l);	
			}
		}
		dfs1(1,1);
		dfs2(1,1);
		T.build(1,n,1);
		if (sum==val){
			p1.solve();
			return 0;
		}
		else {
			p2.solve();
			return 0;
		}
	}
	return 0;
}

Measured memory_bytes: 512