#include using namespace std; typedef long long ll; #define REP(i,n) for(int i=0,_n=(int)(n);i<_n;++i) #define ALL(v) (v).begin(),(v).end() #define CLR(t,v) memset(t,(v),sizeof(t)) templateostream& operator<<(ostream& os,const pair&a){return os<<"("<void chmin(T&a,const T&b){if(a>b)a=b;} templatevoid chmax(T&a,const T&b){if(avoid pv(T a,T b){for(T i=a;i!=b;++i)cerr<<(*i)<<" ";cerr<void pv(T a,T b){} #endif ll nextLong() { ll x; scanf("%lld", &x); return x;} const ll MOD = 1e9 + 7; struct mint { ll x; mint(ll x=0):x((x%MOD+MOD)%MOD){} mint& operator+=(const mint a) {if ((x += a.x) >= MOD) x -= MOD;return *this;} mint& operator-=(const mint a) {if ((x += MOD-a.x) >= MOD) x -= MOD;return *this;} mint& operator*=(const mint a) {(x *= a.x) %= MOD;return *this;} mint operator+(const mint a) const {mint res(*this);return res+=a;} mint operator-(const mint a) const {mint res(*this);return res-=a;} mint operator*(const mint a) const {mint res(*this);return res*=a;} mint pow(ll b) const { mint res(1), a(*this); while (b) { if (b & 1) res *= a; a *= a; b >>= 1; } return res; } // for prime MOD mint inv() const {return pow(MOD-2);} mint& operator/=(const mint a) {return (*this) *= a.inv();} mint operator/(const mint a) const {mint res(*this);return res/=a;} }; ostream& operator<<(ostream& os, const mint& a) {os << a.x; return os;} struct UnionFind { vector data; // 根の場合は集合の大きさ*-1、子の場合は親の番号が入る UnionFind(int size) : data(size, -1) { } bool link(int x, int y) { //新たな併合を行うとtrue x = root(x); y = root(y); if (x != y) { if (data[y] < data[x]) swap(x, y); data[x] += data[y]; data[y] = x; } return x != y; } int root(int x) { // 代表元を返す return data[x] < 0 ? x : data[x] = root(data[x]); } int size(int x) { // 要素xが含まれる集合の大きさ return -data[root(x)]; } bool same(int x, int y) { // 同じ集合ならtrue return root(x) == root(y); } int num() { // 異なる集合の数 int res = 0; REP(i, data.size()) res += root(i) == i; return res; } }; struct Edge { int a, b, z; }; vector es; vector< vector > g; const int MAX_N = 212345; int sz[MAX_N]; int dfs(int cur, int prev) { int res = 1; for (int eid : g[cur]) { int nxt = es[eid].a ^ es[eid].b ^ cur; if (nxt == prev) continue; int c = dfs(nxt, cur); sz[eid] = c; res += c; } return res; } int main2() { int N = nextLong(); int M = nextLong(); ll X = nextLong(); UnionFind uf(N); es.clear(); g = vector< vector >(N); REP(i, M) { int a = nextLong() - 1; int b = nextLong() - 1; int z = nextLong(); if (uf.link(a, b)) { g[a].push_back(es.size()); g[b].push_back(es.size()); es.push_back((Edge){a, b, z}); } } CLR(sz, 0); dfs(0, -1); mint ans = 0; for (int i = 0; i < (int)es.size(); i++) { ans += mint(sz[i]) * mint(N - sz[i]) * mint(X).pow(es[i].z); } cout << ans << endl; return 0; } int main() { #ifdef LOCAL for (;!cin.eof();cin>>ws) #endif main2(); return 0; }