#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define ll long long
using namespace std;
inline ll read(){
ll x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int N=2505,P=1e9+7;
int ecnt,head[N];
struct Edge{
int to,nxt,w;
}e[N<<1];
inline void add(int u,int v,int w){
e[++ecnt]={v,head[u],w};head[u]=ecnt;
}
int n,m,X,Y,cnt,fa[N],col[N];
ll ans,f[N][2],g[N][2],sum[N][N],tot[N][N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void color(int u,int f,int id){//对同一个连通块染色
col[u]=id;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f)continue;
color(v,u,id);
}
}
void dfs(int u,int f,int len){//单个树上路径统计
if(f){
int c=col[u],l=min(len,Y);
sum[c][l]=(sum[c][l]+len)%P;
++tot[c][l];
}
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f)continue;
dfs(v,u,len+e[i].w);
}
}
int main(){
//freopen("mooriokart.in","r",stdin);
//freopen("mooriokart.out","w",stdout);
n=read(),m=read(),X=read(),Y=read();
rep(i,1,n)fa[i]=i;
rep(i,1,m){
int u=read(),v=read(),w=read();
add(u,v,w);add(v,u,w);
fa[find(u)]=find(v);
}
rep(i,1,n)if(i==find(i))color(i,0,++cnt);
rep(i,1,n)dfs(i,0,0);
//dp(卷积合并答案)
int cur=min(cnt*X,Y);
f[cur][0]=1,f[cur][1]=X*cnt;
rep(i,1,cnt){
rep(j,cur,Y){
g[j][0]=f[j][0],g[j][1]=f[j][1];
f[j][0]=f[j][1]=0;
}
rep(j,0,Y){
if(!tot[i][j])continue;
rep(k,cur,Y){
if(!g[k][0])continue;
int l=min(j+k,Y);
f[l][0]=(f[l][0]+tot[i][j]*g[k][0]%P)%P;
f[l][1]=(f[l][1]+sum[i][j]*g[k][0]%P+tot[i][j]*g[k][1])%P;
}
}
}
ans=f[Y][1];
rep(i,1,cnt-1)ans=ans*i%P;
printf("%lld\n",ans*((P+1)/2)%P);
return 0;
}