#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std; 
const int N=2005;
const int P=1000000007;
struct edge{ 
	int v,len;
	edge *next; 
}pool[600005],*h[N];

int n,m,top=-1; 
long long C,res;
long long ans;
int p[N],cnt_w,cnt_b;

inline long long ksm(long long base,long long x){
	long long wes=1; 	
	while(x){ 		
		if(x&1) wes*=base,wes%=P; 
		base*=base,base%=P; 	
		x>>=1; 
	} 
	return wes; 
} 

inline void addedge(int u,int v,int len){
	edge *tmp=&pool[++top]; 
	tmp->v=v;tmp->next=h[u];h[u]=tmp;
	tmp->len=len;
}
struct task{ 
	int u,v,len; 	
	int type; 	
	inline task(){} 	
	inline task(int _u,int _v,int _len){ 		
		u=_u; 		
		v=_v; 		
		len=_len; 	
	} 	
	inline void add(){ 		
		addedge(u,v,len); 		
		addedge(v,u,len); 	
	} 	
	inline bool operator<(const task &w)const{ 		
		return len<w.len; 	
	} 
}a[N]; 

int find(int x){ 	
	if(p[x]==0) return x; 	
	return p[x]=find(p[x]); 
} 

inline bool onion(int x,int y){ 	
	x=find(x); y=find(y); 	
	if(x==y) return false; 	
	p[x]=y; 	
	return true; 
} 

inline bool test_onion(int x,int y){ 	
	x=find(x); y=find(y); 	
	if(x==y) return false; 	
	return true; 
} 

/*
int dfs(int u,int pre,int T){ 	
	if(u==T) return 0; 	int wes=-1; 	
	for(edge *tmp=h[u];tmp!=NULL;tmp=tmp->next){ 		
		int v=tmp->v; 		
		if(v==pre) continue; 		
		int w=dfs(v,u,T); 		
		if(w!=-1) wes=max(wes,max(tmp->len,w)); 	
	} 	
	return wes; 
} 
*/

int fa[N][19];
int plen[N][19];
int dep[N];

void dfs(int u,int pre,int prelen){
	p[u]=pre;
	fa[u][0]=pre;
	plen[u][0]=prelen;
	dep[u]=dep[pre]+1;
	for(int i=1;i<19;i++){
		fa[u][i]=fa[fa[u][i-1]][i-1];
		plen[u][i]=max(plen[u][i-1],plen[fa[u][i-1]][i-1]);
	}
	for(edge *tmp=h[u];tmp!=NULL;tmp=tmp->next){
		int v=tmp->v;
		if(v==pre) continue;
		dfs(v,u,tmp->len);
	}
}

inline int query(int u,int v){
	int res=0;
	if(dep[u]<dep[v]) swap(u,v);
	while(dep[u]>dep[v]){
		int len=0;
		while(dep[fa[u][len+1]]>dep[v]) len++;
		res=max(res,plen[u][len]); u=fa[u][len];
	}
	while(u!=v){
		int len=0;
		while(fa[u][len+1]!=fa[v][len+1]) len++;
		res=max(res,plen[u][len]); u=fa[u][len];
		res=max(res,plen[v][len]); v=fa[v][len];
	}
	return res;
}

#define multi(x,y) ((x)*(y)%P) 

void init(){ 	
	int x1,x2,x3; 	
	scanf("%d%d%lld",&n,&m,&C); 	
	for(int i=1;i<=m;i++){ 		
		scanf("%d%d%d",&x1,&x2,&x3); 		
		a[i]=task(x1,x2,x3); 	
	} 	
	sort(a+1,a+m+1); 	
	for(int i=1;i<=m;){ 		
		int j=i; 		
		while(a[j+1].len==a[i].len) j++; 		
		for(int t=i;t<=j;t++) if(test_onion(a[t].u,a[t].v)==true) a[t].type=true,cnt_w++; //cnt_w : number of whites 		
		for(int t=i;t<=j;t++) if(onion(a[t].u,a[t].v)==true) res+=a[t].len; //res : sum of whites 		
		i=j+1; 	
	} 
	if(res==C){ 		
		printf("%lld\n",(P+ksm(2,m)-ksm(2,m-cnt_w+1))%P); 		
		return ; 	
	}
	memset(p,0,sizeof(p)); 	
	for(int i=1;i<=m;i++){ 		
		if(a[i].type==true){ 			
			if(onion(a[i].u,a[i].v)==true) a[i].add(); 			
			continue; 		
		} 	
	}
	dfs(1,0,0);
	
	for(int i=1;i<=m;i++){ 		
		if(a[i].type==true) continue; 		
		int maxlen=query(a[i].u,a[i].v); 		
		if(res-maxlen+a[i].len<C) cnt_w++; 		
		if(res-maxlen+a[i].len==C) cnt_b++; 	
	} 
	//printf("qwq\n"); 	
	//printf("m=%d , w=%d , b=%d\n",m,cnt_w,cnt_b); 	
	printf("%lld\n",(P+ksm(2,m-cnt_w+1)-ksm(2,m-cnt_w-cnt_b+1))%P); 
} 

int main(){ 	
	init(); 	
	return 0; 
}


Measured memory_bytes: 512