""" zi!=zjなので、パスの最短距離はそこに含まれるzの最大値で決まる。 パスに含まれる辺の本数がどれだけ大きくてもzの最大値が他のパスより小さければそのパスが最短になる。 ziの小さい順にグラフに辺を追加していく。unionFind 木ができる。あとはやるだけ。 """ def main0(n,m,x,uvz): mod=10**9+7 from heapq import heappop,heappush g=[[] for _ in range(n)] for u,v,z in uvz: u,v=u-1,v-1 g[u].append([v,pow(x,z)]) g[v].append([u,pow(x,z)]) ans=0 inf=float('inf') for i in range(n-1): seen=[inf]*n todo=[[0,i]] seen[i]=0 while todo: c,v=heappop(todo) if seen[v]seen[v]+nc: seen[nv]=seen[v]+nc heappush(todo,[seen[nv],nv]) ans+=sum(seen[i+1:]) ans%=mod return ans # UnionFind class UnionFind: def __init__(self,n): self.n=n self.par=[-1]*n # par[i]:i根ならグループiの要素数に-1をかけたもの。i根じゃないならiの親 self.rank=[0]*n # iの根を返す def find(self,i): if self.par[i]<0:return i ii=i while self.par[i]>=0: i=self.par[i] while i!=self.par[ii]: ii,self.par[ii]=self.par[ii],i return i # iとjをunionし、根頂点を返す def union(self,i,j): i,j=self.find(i),self.find(j) if i==j:return i elif self.rank[i]>self.rank[j]: # par[i]:グループiの要素数で判断してもいい self.par[i]+=self.par[j] self.par[j]=i else: self.par[j]+=self.par[i] self.par[i]=j # 深さ(rank)が同じものを併合した場合1を足す if self.rank[i]==self.rank[j]: self.rank[j]+=1 return self.find(i) # iとjが同じグループに属するか判断 def same(self,i,j): return self.find(i)==self.find(j) # ノードiが属する木のサイズを返す def size(self,i): return -self.par[self.find(i)] def main1(n,m,x,uvz): mod=10**9+7 uf=UnionFind(n) ans=0 ki=[[] for _ in range(n)] for u,v,z in uvz: u,v=u-1,v-1 if uf.same(u,v):continue uf.union(u,v) ki[v].append([u,pow(x,z,mod)]) ki[u].append([v,pow(x,z,mod)]) dfs_order=[] par=[None]*n todo=[[0,-1]] while todo: v,p=todo.pop() dfs_order.append(v) for nv,nc in ki[v]: if nv==p:continue todo.append([nv,v]) par[nv]=v,nc dfs_order.reverse() ans=0 dp=[1]*n for v in dfs_order[:-1]: p,c=par[v] ans+=c*dp[v]*(n-dp[v]) ans%=mod dp[p]+=dp[v] return ans if __name__=='__main__': n,m,x=map(int,input().split()) uvz=[list(map(int,input().split())) for _ in range(m)] #ret0=main0(n,m,x,uvz) ret1=main1(n,m,x,uvz) #print(ret0) print(ret1)