#include <bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(auto i=(a); i<(b); ++i)
#define trav(a,x) for(auto& a: x)
#define all(x) begin(x),end(x)
#define sz(x) (int)size(x)
#define PB push_back
using ll = long long;
using ld = long double;
using pii = pair<int,int>;
using vi = vector<int>;

struct edge{int to, w;};
using graph = vector<vector<edge>>;

auto getindex(pii i_deg, int k) {
  return i_deg.second * k + i_deg.first;
}

struct DSU {
  vi par;
  DSU(int n) : par(n, -1) {}
  int find(int i) {return par[i] < 0 ? i : (par[i] = find(par[i]));}
  bool join(int i, int j) {
    i = find(i); j = find(j);
    if (i == j) return false;
    par[i] += par[j];
    par[j] = i;
    return false;
  }
};

int backtrack(int deg, int k, int n, auto& used, auto& dsu, const auto& freq, int nodes_into = 0) {
  if (deg > k) {
    assert(nodes_into <= n);
    return nodes_into < n ? 0 : 1;
  }
  auto ways = 0;
  rep(i, 0, deg) {
    auto ind = getindex({i, deg}, k);
    auto component = dsu.find(ind);
    if (used[component]) continue;
    used[component] = true;
    ways += backtrack(deg + 1, k, n, used, dsu, freq, nodes_into + freq[ind]);
    used[component] = false;
  }
  return ways;
}

int main() {
  cin.sync_with_stdio(0); cin.tie(0);
  cin.exceptions(cin.failbit);

  int n, m, k;
  cin >> n >> m >> k;
  graph g(n);
  rep(it, 0, m) {
    int u, v, w;
    cin >> u >> v >> w;
    --u; --v;
    g[u].PB({v, w});
  }
  vector<vector<pii>> t(n); // coordinate compressed transpose
  rep(i, 0, n) {
    sort(all(g[i]), [](const auto& e1, const auto& e2){return e1.w < e2.w;});
    auto deg = sz(g[i]);
    rep(d, 0, deg) {
      auto e = g[i][d];
      t[e.to].PB({d, deg});
    }
  }
  rep(i, 0, n) {
    sort(all(t[i]));
    t[i].erase(unique(all(t[i])), end(t[i]));
  }
  auto nn = (k + 1) * (k + 1);
  DSU dsu(nn);
  vi freq(nn);
  rep(i, 0, n) {
    if (empty(t[i])) continue;
    auto root = getindex(t[i].back(), k);
    trav(inedge, t[i]) {
      auto ind = getindex(inedge, k);
      freq[ind]++;
      dsu.join(root, ind);
    }
  }
  vi used_component(nn);
  auto sol = backtrack(1, k, n, used_component, dsu, freq);
  cout << sol << '\n';
}


#include <bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(auto i=(a); i<(b); ++i)
#define trav(a,x) for(auto& a: x)
#define all(x) begin(x),end(x)
#define sz(x) (int)size(x)
#define PB push_back
using ll = long long;
using ld = long double;
using pii = pair<int,int>;
using vi = vector<int>;

struct edge{int to, w;};
using graph = vector<vector<edge>>;

auto getindex(const pii& i_deg, int k) {
  return i_deg.second * (k + 1) + i_deg.first;
}

int backtrack(int deg, int k, auto& used, const auto& conflict) {
  assert(sz(used) < deg);
  if (deg > k) return 1;
  auto ways = 0;
  rep(i, 0, deg) {
    auto ind = getindex({i, deg}, k);
    if (conflict[ind][ind]) continue;
    if (!all_of(all(used), [&](int j){return !conflict[ind][j];})) continue;
    used.PB(ind);
    ways += backtrack(deg + 1, k, used, conflict);
    used.pop_back();
  }
  return ways;
}

int main() {
  cin.sync_with_stdio(0); cin.tie(0);
  cin.exceptions(cin.failbit);

  int n, m, k;
  cin >> n >> m >> k;
  graph g(n);
  rep(it, 0, m) {
    int u, v, w;
    cin >> u >> v >> w;
    --u; --v;
    g[u].PB({v, w});
  }
  vector<vector<pii>> t(n);
  rep(i, 0, n) {
    sort(all(g[i]), [](const auto& e1, const auto& e2){return e1.w < e2.w;});
    auto deg = sz(g[i]);
    rep(d, 0, deg) {
      auto e = g[i][d];
      t[e.to].PB({d, deg});
    }
  }
  auto nn = (k + 1) * (k + 1);
  auto conflict = vector(nn, vi(nn));
  rep(i, 0, n) {
    sort(all(t[i]));
    rep(it, 0, sz(t[i]) - 1) {
      if (t[i][it] == t[i][it + 1]) {
	auto ind = getindex(t[i][it], k);
	conflict[ind][ind] = true;
      }
    }
    t[i].erase(unique(all(t[i])), end(t[i]));
    rep(it1, 0, sz(t[i])) {
      auto ind = getindex(t[i][it1], k);
      rep(it2, it1 + 1, sz(t[i])) {
	auto ind2 = getindex(t[i][it2], k);
	conflict[ind][ind2] = conflict[ind2][ind] = true;
      }
    }
  }
  vi used;
  auto sol = backtrack(1, k, used, conflict);
  cout << sol << '\n';
}


#include <bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(auto i=(a); i<(b); ++i)
#define trav(a,x) for(auto& a: x)
#define all(x) begin(x),end(x)
#define sz(x) (int)size(x)
#define PB push_back
using ll = long long;
using ld = long double;
using pii = pair<int,int>;
using vi = vector<int>;

struct edge{int to, w;};
using graph = vector<vector<edge>>;

auto getindex(pii i_deg, int k) {
  return i_deg.second * k + i_deg.first;
}

int backtrack(int deg, int k, int n, auto& used, auto& conflict, const auto& freq, int nodes_into = 0) {
  if (deg > k) {
    assert(nodes_into == n);
    return 1;
  }
  auto ways = 0;
  rep(i, 0, deg) {
    auto ind = getindex({i, deg}, k);

    bool good = true;
    trav(j, used) good &= !conflict[ind][j];
    if (!good) continue;

    used.PB(ind);
    ways += backtrack(deg + 1, k, n, used, conflict, freq, nodes_into + freq[ind]);
    used.pop_back();
  }
  return ways;
}

int main() {
  cin.sync_with_stdio(0); cin.tie(0);
  cin.exceptions(cin.failbit);

  int n, m, k;
  cin >> n >> m >> k;
  graph g(n);
  rep(it, 0, m) {
    int u, v, w;
    cin >> u >> v >> w;
    --u; --v;
    g[u].PB({v, w});
  }
  vector<vector<pii>> t(n); // coordinate compressed transpose
  rep(i, 0, n) {
    sort(all(g[i]), [](const auto& e1, const auto& e2){return e1.w < e2.w;});
    auto deg = sz(g[i]);
    rep(d, 0, deg) {
      auto e = g[i][d];
      t[e.to].PB({d, deg});
    }
  }
  auto nn = (k + 1) * (k + 1);
  auto conflict = vector(nn, vi(nn));
  vi freq(nn);
  rep(i, 0, n) {
    trav(inedge, t[i]) {
      auto ind = getindex(inedge, k);
      trav(inedg2, t[i]) {
	auto ind2 = getindex(inedg2, k);
	conflict[ind][ind2] = conflict[ind2][ind] = true;
      }
      freq[ind]++;
    }
  }
  vi used(nn);
  auto sol = backtrack(1, k, n, used, conflict, freq);
  cout << sol << '\n';
}


#include<bits/stdc++.h>
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
#define st first
#define nd second
#define pb(x) push_back(x)
#define mp(a, b) make_pair(a, b)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

using namespace std;

///~~~~~~~~~~~~~~~~~~~~~~~~~~

void debug(){cerr<<"\n";}
template <typename H, typename... T>
void debug(H h, T... t) {cerr<<h; if (sizeof...(t)) cerr << ", "; debug(t...);}
#define deb(x...) cerr<<#x<<" = ";debug(x);

///~~~~~~~~~~~~~~~~~~~~~~~~~

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<pair<int, int> > vii;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N=2e5+5, INF=1e9+5, mod=1e9+7, K=100;
vector<pii> E[N];
vector<int> tab[K];
int deg[N], gdzie[N];
int cnt=0, k, n;

void gen(int l){
    if(l==k+1){
        cnt++;
        return;
    }
    for(int i=0; i<l; i++){
        int czy=1;
        for(int j:tab[l]){
            if(deg[E[j][i].nd]==1){
                czy=0;
                break;
            }
        }
        if(czy){
            //cout<<"a";
            for(int j:tab[l]){
                deg[E[j][i].nd]=1;
                gdzie[j]=E[j][i].nd;
            }
            gen(l+1);
            for(int j:tab[l]){
                deg[E[j][i].nd]=0;
            }
        }
    }
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int m;
    cin>>n>>m>>k;
    for(int i=0; i<m; i++){
        int u, v, w;
        cin>>u>>v>>w;
        E[u].push_back({w, v});
    }
    for(int i=1; i<=n; i++){
        if(E[i].size()==0){cout<<"0";return 0;}
        sort(all(E[i]));
        for(int j=0; j<E[i].size(); j++){
            E[i][j].st=j;
        }
        tab[E[i].size()].pb(i);
    }
    gen(1);
    cout<<cnt;
}


#include<bits/stdc++.h>

#define st first
#define nd second
#define pb(x) push_back(x)
#define mp(a, b) make_pair(a, b)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

using namespace std;

///~~~~~~~~~~~~~~~~~~~~~~~~~~

void debug(){cerr<<"\n";}
template <typename H, typename... T>
void debug(H h, T... t) {cerr<<h; if (sizeof...(t)) cerr << ", "; debug(t...);}
#define deb(x...) cerr<<#x<<" = ";debug(x);

///~~~~~~~~~~~~~~~~~~~~~~~~~

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<pair<int, int> > vii;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N=2e5+5, INF=1e9+5, mod=1e9+7, K=100;
vector<pii> E[N];
vector<int> in[N];
int czy[K][K];
int tab[K], cnt=0, k, n;
vector<int> zle;
void gen(int l){
    //cout<<l<<"a\n";
    if(l==k+1){
        //cout<<tab[1]<<tab[2]<<tab[3]<<tab[4]<<"\n";
        /*int u=1;
        for(int i=0; i<n; i++){
            u=E[u][tab[E[u].size()]].nd;
            if(u==1){
                if(i==n-1)cnt++;
                else break;
            }
        }*/
        cnt++;
        return;
    }
    for(int i=0; i<l; i++){
        int t=l*k+i;
        bool c=0;
        for(int j:zle)if(czy[j][t]){c=1;break;}
        if(czy[t][t])c=1;
        //cout<<t<<"\n";
        if(!c){
            //cout<<"+"<<t<<"\n";
            zle.push_back(t);
            tab[l]=i;
            gen(l+1);
            zle.pop_back();
            //cout<<"-"<<t<<"\n";
        }
    }
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int m;
    cin>>n>>m>>k;
    for(int i=0; i<m; i++){
        int u, v, w;
        cin>>u>>v>>w;
        E[u].push_back({w, v});
    }
    for(int i=1; i<=n; i++){
        sort(all(E[i]));
        for(int j=0; j<E[i].size(); j++){
            in[E[i][j].nd].push_back(j+k*E[i].size());
        }
    }
    for(int i=1; i<=n; i++){
        if(in[i].size()==0){cout<<"0"; return 0;}
        for(int j=0; j<in[i].size(); j++){
            for(int k=j+1; k<in[i].size(); k++){
                czy[in[i][j]][in[i][k]]=1;
            }
        }
    }
    for(int i=0; i<K; i++){
        for(int j=0; j<K; j++){
            if(czy[i][j])czy[j][i]=1;
        }
    }
    //for(int i=0; i<15; i++)for(int j=0; j<15; j++)cout<<czy[i][j]<<" \n"[j==14];
    gen(1);
    cout<<cnt;
}


#include<bits/stdc++.h>

#define st first
#define nd second
#define pb(x) push_back(x)
#define mp(a, b) make_pair(a, b)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

using namespace std;

///~~~~~~~~~~~~~~~~~~~~~~~~~~

void debug(){cerr<<"\n";}
template <typename H, typename... T>
void debug(H h, T... t) {cerr<<h; if (sizeof...(t)) cerr << ", "; debug(t...);}
#define deb(x...) cerr<<#x<<" = ";debug(x);

///~~~~~~~~~~~~~~~~~~~~~~~~~

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<pair<int, int> > vii;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N=2e5+5, INF=1e9+5, mod=1e9+7, K=100;
vector<pii> E[N];
vector<int> in[N];
int czy[K][K];
int tab[K], cnt=0, k, n;
vector<int> zle;
void gen(int l){
    //cout<<l<<"a\n";
    if(l==k+1){
        //cout<<tab[1]<<tab[2]<<tab[3]<<"\n";
        int u=1;
        for(int i=0; i<n; i++){
            u=E[u][tab[E[u].size()]].nd;
            if(u==1){
                if(i==n-1)cnt++;
                else break;
            }
        }
        return;
    }
    for(int i=0; i<l; i++){
        int t=l*k+i;
        bool c=0;
        for(int j:zle)if(czy[j][t] || czy[t][j])c=1;
        //cout<<t<<"\n";
        if(!c){
            //cout<<"+"<<t<<"\n";
            zle.push_back(t);
            tab[l]=i;
            gen(l+1);
            zle.pop_back();
            //cout<<"-"<<t<<"\n";
        }
    }
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int m;
    cin>>n>>m>>k;
    for(int i=0; i<m; i++){
        int u, v, w;
        cin>>u>>v>>w;
        E[u].push_back({w, v});
    }
    for(int i=1; i<=n; i++){
        if(E[i].size()==0){cout<<"0";return 0;}
        sort(all(E[i]));
        for(int j=0; j<E[i].size(); j++){
            E[i][j].st=j;
            in[E[i][j].nd].push_back(j+k*E[i].size());
            //cout<<E[i][j].nd<<" "<<j+k*E[i].size()<<"\n";
        }
    }
    for(int i=1; i<=n; i++){
        if(in[i].size()==0){cout<<"0"; return 0;}
        for(int j=0; j<in[i].size(); j++){
            for(int k=j+1; k<in[i].size(); k++){
                czy[in[i][j]][in[i][k]]=1;
                czy[in[i][k]][in[i][j]]=1;
            }
        }
    }
    //for(int i=0; i<15; i++)for(int j=0; j<15; j++)cout<<czy[i][j]<<" \n"[j==14];
    gen(1);
    cout<<cnt;
}


#include<bits/stdc++.h>

#define st first
#define nd second
#define pb(x) push_back(x)
#define mp(a, b) make_pair(a, b)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

using namespace std;

///~~~~~~~~~~~~~~~~~~~~~~~~~~

void debug(){cerr<<"\n";}
template <typename H, typename... T>
void debug(H h, T... t) {cerr<<h; if (sizeof...(t)) cerr << ", "; debug(t...);}
#define deb(x...) cerr<<#x<<" = ";debug(x);

///~~~~~~~~~~~~~~~~~~~~~~~~~

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<pair<int, int> > vii;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N=2e5+5, INF=1e9+5, mod=1e9+7, K=100;
vector<pii> E[N];
vector<int> in[N];
int czy[K][K], czy2[K];
int tab[K], cnt=0, k, n;
vector<int> zle;
void gen(int l){
    //cout<<l<<"a\n";

    if(l==k+1){
        //cout<<tab[1]<<tab[2]<<tab[3]<<tab[4]<<"\n";
        /*int u=1;
        for(int i=0; i<n; i++){
            u=E[u][tab[E[u].size()]].nd;
            if(u==1){
                if(i==n-1)cnt++;
                else break;
            }
        }*/
        cnt++;
        return;
    }
    if(!czy2[l]){
        gen(l+1);
        return;
    }
    for(int i=0; i<l; i++){
        int t=l*k+i;
        bool c=0;
        for(int j:zle)if(czy[j][t]){c=1;break;}
        if(czy[t][t])c=1;
        //cout<<t<<"\n";
        if(!c){
            //cout<<"+"<<t<<"\n";
            zle.push_back(t);
            tab[l]=i;
            gen(l+1);
            zle.pop_back();
            //cout<<"-"<<t<<"\n";
        }
    }
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int m;
    cin>>n>>m>>k;
    for(int i=0; i<m; i++){
        int u, v, w;
        cin>>u>>v>>w;
        E[u].push_back({w, v});
    }
    for(int i=1; i<=n; i++){
        czy2[E[i].size()]=1;
        sort(all(E[i]));
        for(int j=0; j<E[i].size(); j++){
            in[E[i][j].nd].push_back(j+k*E[i].size());
        }
    }
    for(int i=1; i<=n; i++){
        if(in[i].size()==0){cout<<"0"; return 0;}
        for(int j=0; j<in[i].size(); j++){
            for(int k=j+1; k<in[i].size(); k++){
                czy[in[i][j]][in[i][k]]=1;
            }
        }
    }
    for(int i=0; i<K; i++){
        for(int j=0; j<K; j++){
            if(czy[i][j])czy[j][i]=1;
        }
    }
    //for(int i=0; i<15; i++)for(int j=0; j<15; j++)cout<<czy[i][j]<<" \n"[j==14];
    gen(1);
    for(int i=1; i<=k; i++){
        if(!czy2[i])cnt*=i;
    }
    cout<<cnt;
}


#include<bits/stdc++.h>

#define st first
#define nd second
#define pb(x) push_back(x)
#define mp(a, b) make_pair(a, b)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

using namespace std;

///~~~~~~~~~~~~~~~~~~~~~~~~~~

void debug(){cerr<<"\n";}
template <typename H, typename... T>
void debug(H h, T... t) {cerr<<h; if (sizeof...(t)) cerr << ", "; debug(t...);}
#define deb(x...) cerr<<#x<<" = ";debug(x);

///~~~~~~~~~~~~~~~~~~~~~~~~~

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<pair<int, int> > vii;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N=2e5+5, INF=1e9+5, mod=1e9+7, K=100;
vector<pii> E[N];
vector<int> in[N];
int czy[K][K];
int tab[K], cnt=0, k, n;
vector<int> zle;
void gen(int l){
    //cout<<l<<"a\n";
    if(l==k+1){
        //cout<<tab[1]<<tab[2]<<tab[3]<<tab[4]<<"\n";
        /*int u=1;
        for(int i=0; i<n; i++){
            u=E[u][tab[E[u].size()]].nd;
            if(u==1){
                if(i==n-1)cnt++;
                else break;
            }
        }*/
        cnt++;
        return;
    }
    for(int i=0; i<l; i++){
        int t=l*k+i;
        bool c=0;
        for(int j:zle)if(czy[j][t] || czy[t][j]){c=1;break;}
        if(czy[t][t])c=1;
        //cout<<t<<"\n";
        if(!c){
            //cout<<"+"<<t<<"\n";
            zle.push_back(t);
            tab[l]=i;
            gen(l+1);
            zle.pop_back();
            //cout<<"-"<<t<<"\n";
        }
    }
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int m;
    cin>>n>>m>>k;
    for(int i=0; i<m; i++){
        int u, v, w;
        cin>>u>>v>>w;
        E[u].push_back({w, v});
    }
    for(int i=1; i<=n; i++){
        if(E[i].size()==0){cout<<"0";return 0;}
        sort(all(E[i]));
        for(int j=0; j<E[i].size(); j++){
            E[i][j].st=j;
            in[E[i][j].nd].push_back(j+k*E[i].size());
            //cout<<E[i][j].nd<<" "<<j+k*E[i].size()<<"\n";
        }
    }
    for(int i=1; i<=n; i++){
        if(in[i].size()==0){cout<<"0"; return 0;}
        for(int j=0; j<in[i].size(); j++){
            for(int k=j+1; k<in[i].size(); k++){
                czy[in[i][j]][in[i][k]]=1;
                czy[in[i][k]][in[i][j]]=1;
            }
        }
    }
    //for(int i=0; i<15; i++)for(int j=0; j<15; j++)cout<<czy[i][j]<<" \n"[j==14];
    gen(1);
    cout<<cnt;
}


#include<bits/stdc++.h>
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
#define st first
#define nd second
#define pb(x) push_back(x)
#define mp(a, b) make_pair(a, b)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

using namespace std;

///~~~~~~~~~~~~~~~~~~~~~~~~~~

void debug(){cerr<<"\n";}
template <typename H, typename... T>
void debug(H h, T... t) {cerr<<h; if (sizeof...(t)) cerr << ", "; debug(t...);}
#define deb(x...) cerr<<#x<<" = ";debug(x);

///~~~~~~~~~~~~~~~~~~~~~~~~~

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<pair<int, int> > vii;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N=2e5+5, INF=1e9+5, mod=1e9+7, K=100;
vector<pii> E[N];
vector<int> tab[K];
int deg[N], gdzie[N];
int cnt=0, k, n;

void gen(int l){
    if(l==k+1){
        /*for(int i=1; i<=n; i++)cout<<deg[i];
        cout<<"\n";
        int v=1;
        for(int i=0; i<n-1; i++){
            v=gdzie[v];
            if(v==1)return;
        }
        if(gdzie[v]==1)*/cnt++;
        return;
    }
    for(int i=0; i<l; i++){
        int czy=1;
        for(int j=0; j<tab[l].size(); j++){
            if(deg[E[tab[l][j]][i].nd]==1){
                for(int c=j-1; c>=0; c--){
                    deg[E[tab[l][c]][i].nd]=0;
                }
                czy=0;
                break;
                //gdzie[j]=E[j][i].nd;
            }
            deg[E[tab[l][j]][i].nd]=1;
        }
        if(czy==1){
            gen(l+1);
            for(int j:tab[l]){
                deg[E[j][i].nd]--;
            }
        }
    }
}
int main(){
    //ios_base::sync_with_stdio(false);
    //cin.tie(NULL);
    //cout.tie(NULL);
    int m;
    cin>>n>>m>>k;
    for(int i=0; i<m; i++){
        int u, v, w;
        cin>>u>>v>>w;
        E[u].push_back({w, v});
    }
    for(int i=1; i<=n; i++){
        //if(E[i].size()==0){cout<<"0";return 0;}
        sort(all(E[i]));
        //for(int j=0; j<E[i].size(); j++){
        //    E[i][j].st=j;
        //}
        tab[E[i].size()].pb(i);
    }
    gen(1);
    cout<<cnt;
}


#include<bits/stdc++.h>
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
#define st first
#define nd second
#define pb(x) push_back(x)
#define mp(a, b) make_pair(a, b)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

using namespace std;

///~~~~~~~~~~~~~~~~~~~~~~~~~~

void debug(){cerr<<"\n";}
template <typename H, typename... T>
void debug(H h, T... t) {cerr<<h; if (sizeof...(t)) cerr << ", "; debug(t...);}
#define deb(x...) cerr<<#x<<" = ";debug(x);

///~~~~~~~~~~~~~~~~~~~~~~~~~

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<pair<int, int> > vii;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N=2e5+5, INF=1e9+5, mod=1e9+7, K=100;
vector<pii> E[N];
vector<int> tab[K];
int deg[N], gdzie[N];
int cnt=0, k, n;

void gen(int l){
    if(l==k+1){
        int v=1;
        for(int i=0; i<n-1; i++){
            v=gdzie[v];
            if(v==1)return;
        }
        if(gdzie[v]==1)cnt++;
        return;
    }
    for(int i=0; i<l; i++){
        int czy=1;
        for(int j:tab[l]){
            if(deg[E[j][i].nd]==1){
                czy=0;
                break;
            }
        }
        if(czy){
            //cout<<"a";
            for(int j:tab[l]){
                deg[E[j][i].nd]=1;
                gdzie[j]=E[j][i].nd;
            }
            gen(l+1);
            for(int j:tab[l]){
                deg[E[j][i].nd]=0;
            }
        }
    }
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int m;
    cin>>n>>m>>k;
    for(int i=0; i<m; i++){
        int u, v, w;
        cin>>u>>v>>w;
        E[u].push_back({w, v});
    }
    for(int i=1; i<=n; i++){
        if(E[i].size()==0){cout<<"0";return 0;}
        sort(all(E[i]));
        for(int j=0; j<E[i].size(); j++){
            E[i][j].st=j;
        }
        tab[E[i].size()].pb(i);
    }
    gen(1);
    cout<<cnt;
}


#include<bits/stdc++.h>
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
#define st first
#define nd second
#define pb(x) push_back(x)
#define mp(a, b) make_pair(a, b)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

using namespace std;

///~~~~~~~~~~~~~~~~~~~~~~~~~~

void debug(){cerr<<"\n";}
template <typename H, typename... T>
void debug(H h, T... t) {cerr<<h; if (sizeof...(t)) cerr << ", "; debug(t...);}
#define deb(x...) cerr<<#x<<" = ";debug(x);

///~~~~~~~~~~~~~~~~~~~~~~~~~

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<pair<int, int> > vii;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N=2e5+5, INF=1e9+5, mod=1e9+7, K=100;
vector<pii> E[N];
int vis[N];
int cnt=0, k, n, pelne;
int tab[K];
void gen(int v, int id){
    //cout<<v<<" "<<id<<"\n";
    if(id==n && v==1){
        cnt+=pelne;
        //cout<<pelne;
    }
    if(vis[v]){
        return;
    }
    vis[v]=1;
    if(tab[E[v].size()]!=0){
        gen(E[v][tab[E[v].size()]-1].nd, id+1);
    }
    else for(int i=0; i<E[v].size(); i++){
        tab[E[v].size()]=i+1;
        pelne/=E[v].size();
        gen(E[v][i].nd, id+1);
        pelne*=E[v].size();
        tab[E[v].size()]=0;
    }
    vis[v]=0;
    return;
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int m;
    cin>>n>>m>>k;
    pelne=1;
    for(int i=2; i<=k; i++)pelne*=i;
    for(int i=0; i<m; i++){
        int u, v, w;
        cin>>u>>v>>w;
        E[u].push_back({w, v});
    }
    for(int i=1; i<=n; i++){
        if(E[i].size()==0){cout<<"0";return 0;}
        sort(all(E[i]));
        for(int j=0; j<E[i].size(); j++){
            E[i][j].st=j;
        }
        //tab[E[i].size()].pb(i);
    }
    gen(1, 0);
    cout<<cnt;
}


#include<bits/stdc++.h>

#define st first
#define nd second
#define pb(x) push_back(x)
#define mp(a, b) make_pair(a, b)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

using namespace std;

///~~~~~~~~~~~~~~~~~~~~~~~~~~

void debug(){cerr<<"\n";}
template <typename H, typename... T>
void debug(H h, T... t) {cerr<<h; if (sizeof...(t)) cerr << ", "; debug(t...);}
#define deb(x...) cerr<<#x<<" = ";debug(x);

///~~~~~~~~~~~~~~~~~~~~~~~~~

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<pair<int, int> > vii;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N=2e5+5, INF=1e9+5, mod=1e9+7, K=100;
vector<pii> E[N];
int in[N][K];
int czy[K][K], czy2[K];
int tab[K], cnt=0, k, n;
vector<int> zle;
void gen(int l){
    //cout<<l<<"a\n";

    if(l==k+1){
        //cout<<tab[1]<<tab[2]<<tab[3]<<tab[4]<<"\n";
        /*int u=1;
        for(int i=0; i<n; i++){
            u=E[u][tab[E[u].size()]].nd;
            if(u==1){
                if(i==n-1)cnt++;
                else break;
            }
        }*/
        cnt++;
        return;
    }
    if(!czy2[l]){
        gen(l+1);
        return;
    }
    for(int i=0; i<l; i++){
        int t=l*k+i;
        bool c=0;
        for(int j:zle)if(czy[j][t]){c=1;break;}
        if(czy[t][t])c=1;
        //cout<<t<<"\n";
        if(!c){
            //cout<<"+"<<t<<"\n";
            zle.push_back(t);
            tab[l]=i;
            gen(l+1);
            zle.pop_back();
            //cout<<"-"<<t<<"\n";
        }
    }
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int m;
    cin>>n>>m>>k;
    for(int i=0; i<m; i++){
        int u, v, w;
        cin>>u>>v>>w;
        E[u].push_back({w, v});
    }
    for(int i=1; i<=n; i++){
        czy2[E[i].size()]=1;
        sort(all(E[i]));
        for(int j=0; j<E[i].size(); j++){
            in[E[i][j].nd][j+k*E[i].size()]++;
        }
    }
    for(int i=1; i<=n; i++){
        //if(in[i].size()==0){cout<<"0"; return 0;}
        vi V;
        for(int j=0; j<K; j++){
            if(in[i][j])V.pb(j);
            if(in[i][j]>1)V.pb(j);
        }
        for(int j=0; j<V.size(); j++){
            for(int c=j+1; c<V.size(); c++){
                czy[V[j]][V[c]]=1;
            }
        }
    }
    for(int i=0; i<K; i++){
        for(int j=0; j<K; j++){
            if(czy[i][j])czy[j][i]=1;
        }
    }
    //for(int i=0; i<15; i++)for(int j=0; j<15; j++)cout<<czy[i][j]<<" \n"[j==14];
    gen(1);
    for(int i=1; i<=k; i++){
        if(!czy2[i])cnt*=i;
    }
    cout<<cnt;
}


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
template <class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

template<class T> bool ckmin(T& a, const T& b) {return b < a ? a = b, 1 : 0;}
template<class T> bool ckmax(T& a, const T& b) {return a < b ? a = b, 1 : 0;}

#define FOR(i,a,b) for(int i = a; i < b; i++)
#define F0R(i,a) for(int i = 0; i < a; i++)
#define pb push_back
#define all(x) x.begin(), x.end()
#define sz(x) int((x).size())
#define newl '\n'

#define FAST ios::sync_with_stdio(0); cin.tie(0);
#define finish(x) return cout << x << "\n", 0;
#define bug(x) cerr << ">>> " << #x << " = " << x << "\n";
#define _ << " " <<

const ll MOD = 998244353;
const ll INF = 1e9 + 7;

const int K = 10;
const int MX = 1e5 + 5;
// mutex[i][j][k][l] means ! (c_i == j && c_k == l)
int n, m, kk, bad[K][K][K][K], vis[MX], indeg[MX][100], tot, vals[K];
vector<array<int,3>> adj[MX];

void dfs (int u = 1) {
	vis[u] = 1;
	for (auto &edge : adj[u]) {
		// u --> v
		int weight = edge[0], v = edge[1], idx = edge[2];
		indeg[v][10 * sz(adj[u]) + idx]++;
		if (!vis[v]) dfs(v);
	}
}

void solve (int x = 1) {
	if (x == kk + 1) {
		bool works = 1;
		F0R(i,kk) {
			works &= !bad[i+1][vals[i+1]][i+1][vals[i+1]];
		}
		for (int i = 0; i < kk; ++i) {
			for (int j = i + 1; j < kk; ++j) {
				works &= !bad[i+1][vals[i+1]][j+1][vals[j+1]];
			}
		}
		tot += works;
		return;
	}
	FOR(i,1,x+1) {
		vals[x] = i;
		solve(x + 1);
	}
}

// check int vs ll and precision
// check logic
int main(){ FAST
	// ifstream cin("/Users/konwoo/input.txt");
	// ofstream cout("/Users/konwoo/output.txt");

	cin >> n >> m >> kk;
	F0R(i,m) {
		int u, v, w;
		cin >> u >> v >> w;
		array<int,3> ua {w,v,-1};
		adj[u].emplace_back(ua);
	}
	FOR(i,1,n+1) {
		sort(all(adj[i]));
		FOR(j, 1, sz(adj[i]) + 1) {
			adj[i][j-1][2] = j;
		}
	}
	dfs();
	FOR(i,1,n+1) {
		vector<array<int,2>> bad_pairs;
		F0R(j, 100) {
			int idx = j % 10, siz = (j - idx) / 10;
			if (indeg[i][j] == 1) {
				bad_pairs.emplace_back(array<int,2>{siz, idx});
			}
			else if (indeg[i][j] > 1) {
				bad[siz][idx][siz][idx] = 1;
			}
		}

		for (int j = 0; j < sz(bad_pairs); ++j) {
			for (int k = j + 1; k < sz(bad_pairs); ++k) {
				auto &edge1 = bad_pairs[j], &edge2 = bad_pairs[k];
				bad[edge1[0]][edge1[1]][edge2[0]][edge2[1]] = 1;
				bad[edge2[0]][edge2[1]][edge1[0]][edge1[1]] = 1;
			}
		}
	}
	solve();
	cout << tot << newl;

    return 0;
}


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
template <class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

template<class T> bool ckmin(T& a, const T& b) {return b < a ? a = b, 1 : 0;}
template<class T> bool ckmax(T& a, const T& b) {return a < b ? a = b, 1 : 0;}

#define FOR(i,a,b) for(int i = a; i < b; i++)
#define F0R(i,a) for(int i = 0; i < a; i++)
#define pb push_back
#define all(x) x.begin(), x.end()
#define sz(x) int((x).size())
#define newl '\n'

#define FAST ios::sync_with_stdio(0); cin.tie(0);
#define finish(x) return cout << x << "\n", 0;
#define bug(x) cerr << ">>> " << #x << " = " << x << "\n";
#define _ << " " <<

const ll MOD = 998244353;
const ll INF = 1e9 + 7;

const int K = 10;
const int MX = 2e5 + 5;
// mutex[i][j][k][l] means ! (c_i == j && c_k == l)
int n, m, kk, bad[K][K][K][K], vis[MX], indeg[MX][100], tot, vals[K];
vector<array<int,3>> adj[MX];

void dfs (int u = 1) {
	vis[u] = 1;
	for (auto &edge : adj[u]) {
		// u --> v
		int weight = edge[0], v = edge[1], idx = edge[2];
		indeg[v][10 * sz(adj[u]) + idx]++;
		if (!vis[v]) dfs(v);
	}
}

void solve (int x = 1) {
	if (x == kk + 1) {
		bool works = 1;
		F0R(i,kk) {
			works &= !bad[i+1][vals[i+1]][i+1][vals[i+1]];
		}
		for (int i = 0; i < kk; ++i) {
			for (int j = i + 1; j < kk; ++j) {
				works &= !bad[i+1][vals[i+1]][j+1][vals[j+1]];
			}
		}
		tot += works;
		return;
	}
	FOR(i,1,x+1) {
		vals[x] = i;
		//if (bad[x][i][x][i]) continue;
		solve(x + 1);
	}
}

// check int vs ll and precision
// check logic
int main(){ FAST
	// ifstream cin("/Users/konwoo/input.txt");
	// ofstream cout("/Users/konwoo/output.txt");

	cin >> n >> m >> kk;
	F0R(i,m) {
		int u, v, w;
		cin >> u >> v >> w;
		array<int,3> ua {w,v,-1};
		adj[u].emplace_back(ua);
	}
	FOR(i,1,n+1) {
		sort(all(adj[i]));
		FOR(j, 1, sz(adj[i]) + 1) {
			adj[i][j-1][2] = j;
		}
	}
	FOR(i,1,n+1) {
		if (!vis[i]) dfs(i);
	}
	FOR(i,1,n+1) {
		vector<array<int,2>> bad_pairs;
		F0R(j, 100) {
			int idx = j % 10, siz = (j - idx) / 10;
			if (indeg[i][j] == 1) {
				bad_pairs.emplace_back(array<int,2>{siz, idx});
			}
			else if (indeg[i][j] > 1) {
				bad[siz][idx][siz][idx] = 1;
			}
		}

		for (int j = 0; j < sz(bad_pairs); ++j) {
			for (int k = j + 1; k < sz(bad_pairs); ++k) {
				auto &edge1 = bad_pairs[j], &edge2 = bad_pairs[k];
				bad[edge1[0]][edge1[1]][edge2[0]][edge2[1]] = 1;
				bad[edge2[0]][edge2[1]][edge1[0]][edge1[1]] = 1;
			}
		}
	}
	solve();
	cout << tot << newl;

    return 0;
}


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
template <class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

template<class T> bool ckmin(T& a, const T& b) {return b < a ? a = b, 1 : 0;}
template<class T> bool ckmax(T& a, const T& b) {return a < b ? a = b, 1 : 0;}

#define FOR(i,a,b) for(int i = a; i < b; i++)
#define F0R(i,a) for(int i = 0; i < a; i++)
#define pb push_back
#define all(x) x.begin(), x.end()
#define sz(x) int((x).size())
#define newl '\n'

#define FAST ios::sync_with_stdio(0); cin.tie(0);
#define finish(x) return cout << x << "\n", 0;
#define bug(x) cerr << ">>> " << #x << " = " << x << "\n";
#define _ << " " <<

const ll MOD = 998244353;
const ll INF = 1e9 + 7;

const int K = 10;
const int MX = 2e5 + 5;
// mutex[i][j][k][l] means ! (c_i == j && c_k == l)
int n, m, kk, bad[K][K][K][K], vis[MX], indeg[MX][100], tot, vals[K];
vector<array<int,3>> adj[MX];

void dfs (int u = 1) {
	vis[u] = 1;
	for (auto &edge : adj[u]) {
		// u --> v
		int weight = edge[0], v = edge[1], idx = edge[2];
		indeg[v][10 * sz(adj[u]) + idx]++;
		if (!vis[v]) dfs(v);
	}
}

void solve (int x = 1) {
	if (x == kk + 1) {
		bool works = 1;
		for (int i = 0; i < kk; ++i) {
			for (int j = i + 1; j < kk; ++j) {
				works &= !bad[i+1][vals[i+1]][j+1][vals[j+1]];
			}
		}
		tot += works;
		return;
	}
	FOR(i,1,x+1) {
		vals[x] = i;
		if (bad[x][i][x][i]) continue;
		solve(x + 1);
	}
}

// check int vs ll and precision
// check logic
int main(){ FAST
	// ifstream cin("/Users/konwoo/input.txt");
	// ofstream cout("/Users/konwoo/output.txt");

	cin >> n >> m >> kk;
	F0R(i,m) {
		int u, v, w;
		cin >> u >> v >> w;
		array<int,3> ua {w,v,-1};
		adj[u].emplace_back(ua);
	}
	FOR(i,1,n+1) {
		sort(all(adj[i]));
		FOR(j, 1, sz(adj[i]) + 1) {
			adj[i][j-1][2] = j;
		}
	}
	dfs();
	FOR(i,1,n+1) {
		vector<array<int,2>> bad_pairs;
		F0R(j, 100) {
			int idx = j % 10, siz = (j - idx) / 10;
			if (indeg[i][j] == 1) {
				bad_pairs.emplace_back(array<int,2>{siz, idx});
			}
			else if (indeg[i][j] > 1) {
				bad[siz][idx][siz][idx] = 1;
			}
		}

		for (int j = 0; j < sz(bad_pairs); ++j) {
			for (int k = j + 1; k < sz(bad_pairs); ++k) {
				auto &edge1 = bad_pairs[j], &edge2 = bad_pairs[k];
				bad[edge1[0]][edge1[1]][edge2[0]][edge2[1]] = 1;
				bad[edge2[0]][edge2[1]][edge1[0]][edge1[1]] = 1;
			}
		}
	}
	solve();
	cout << tot << newl;

    return 0;
}


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
template <class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

template<class T> bool ckmin(T& a, const T& b) {return b < a ? a = b, 1 : 0;}
template<class T> bool ckmax(T& a, const T& b) {return a < b ? a = b, 1 : 0;}

#define FOR(i,a,b) for(int i = a; i < b; i++)
#define F0R(i,a) for(int i = 0; i < a; i++)
#define pb push_back
#define all(x) x.begin(), x.end()
#define sz(x) int((x).size())
#define newl '\n'

#define FAST ios::sync_with_stdio(0); cin.tie(0);
#define finish(x) return cout << x << "\n", 0;
#define bug(x) cerr << ">>> " << #x << " = " << x << "\n";
#define _ << " " <<

const ll MOD = 998244353;
const ll INF = 1e9 + 7;

const int K = 10;
const int MX = 1e5 + 5;
// mutex[i][j][k][l] means ! (c_i == j && c_k == l)
int n, m, kk, bad[K][K][K][K], vis[MX], indeg[MX][100], tot, vals[K];
vector<array<int,3>> adj[MX];

void dfs (int u = 1) {
	vis[u] = 1;
	for (auto &edge : adj[u]) {
		// u --> v
		int weight = edge[0], v = edge[1], idx = edge[2];
		indeg[v][10 * sz(adj[u]) + idx]++;
		if (!vis[v]) dfs(v);
	}
}

void solve (int x = 1) {
	if (x == kk + 1) {
		bool works = 1;
		for (int i = 0; i < kk; ++i) {
			for (int j = i + 1; j < kk; ++j) {
				works &= !bad[i+1][vals[i+1]][j+1][vals[j+1]];
			}
		}
		tot += works;
		return;
	}
	FOR(i,1,x+1) {
		vals[x] = i;
		if (bad[x][i][x][i]) continue;
		solve(x + 1);
	}
}

// check int vs ll and precision
// check logic
int main(){ FAST
	// ifstream cin("/Users/konwoo/input.txt");
	// ofstream cout("/Users/konwoo/output.txt");

	cin >> n >> m >> kk;
	F0R(i,m) {
		int u, v, w;
		cin >> u >> v >> w;
		array<int,3> ua {w,v,-1};
		adj[u].emplace_back(ua);
	}
	FOR(i,1,n+1) {
		sort(all(adj[i]));
		FOR(j, 1, sz(adj[i]) + 1) {
			adj[i][j-1][2] = j;
		}
	}
	dfs();
	FOR(i,1,n+1) {
		vector<array<int,2>> bad_pairs;
		F0R(j, 100) {
			int idx = j % 10, siz = (j - idx) / 10;
			if (indeg[i][j] == 1) {
				bad_pairs.emplace_back(array<int,2>{siz, idx});
			}
			else if (indeg[i][j] > 1) {
				bad[siz][idx][siz][idx] = 1;
			}
		}

		for (int j = 0; j < sz(bad_pairs); ++j) {
			for (int k = j + 1; k < sz(bad_pairs); ++k) {
				auto &edge1 = bad_pairs[j], &edge2 = bad_pairs[k];
				bad[edge1[0]][edge1[1]][edge2[0]][edge2[1]] = 1;
				bad[edge2[0]][edge2[1]][edge1[0]][edge1[1]] = 1;
			}
		}
	}
	solve();
	cout << tot << newl;

    return 0;
}


#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
template <class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

template<class T> bool ckmin(T& a, const T& b) {return b < a ? a = b, 1 : 0;}
template<class T> bool ckmax(T& a, const T& b) {return a < b ? a = b, 1 : 0;}

#define FOR(i,a,b) for(int i = a; i < b; i++)
#define F0R(i,a) for(int i = 0; i < a; i++)
#define pb push_back
#define all(x) x.begin(), x.end()
#define sz(x) int((x).size())
#define newl '\n'

#define FAST ios::sync_with_stdio(0); cin.tie(0);
#define finish(x) return cout << x << "\n", 0;
#define bug(x) cerr << ">>> " << #x << " = " << x << "\n";
#define _ << " " <<

const ll MOD = 998244353;
const ll INF = 1e9 + 7;

const int K = 10;
const int MX = 2e5 + 5;
// mutex[i][j][k][l] means ! (c_i == j && c_k == l)
int n, m, kk, bad[K][K][K][K], vis[MX], indeg[MX][100], tot, vals[K];
vector<array<int,3>> adj[MX];

void dfs (int u = 1) {
	vis[u] = 1;
	for (auto &edge : adj[u]) {
		// u --> v
		int weight = edge[0], v = edge[1], idx = edge[2];
		indeg[v][10 * sz(adj[u]) + idx]++;
		if (!vis[v]) dfs(v);
	}
}

void solve (int x = 1) {
	if (x == kk + 1) {
		bool works = 1;
		for (int i = 0; i < kk; ++i) {
			for (int j = i + 1; j < kk; ++j) {
				works &= !bad[i+1][vals[i+1]][j+1][vals[j+1]];
			}
		}
		tot += works;
		return;
	}
	FOR(i,1,x+1) {
		vals[x] = i;
		if (bad[x][i][x][i]) continue;
		solve(x + 1);
	}
}

// check int vs ll and precision
// check logic
int main(){ FAST
	// ifstream cin("/Users/konwoo/input.txt");
	// ofstream cout("/Users/konwoo/output.txt");

	cin >> n >> m >> kk;
	F0R(i,m) {
		int u, v, w;
		cin >> u >> v >> w;
		array<int,3> ua {w,v,-1};
		adj[u].emplace_back(ua);
	}
	FOR(i,1,n+1) {
		sort(all(adj[i]));
		FOR(j, 1, sz(adj[i]) + 1) {
			adj[i][j-1][2] = j;
		}
	}
	FOR(i,1,n+1) {
		if (!vis[i]) dfs(i);
	}
	FOR(i,1,n+1) {
		vector<array<int,2>> bad_pairs;
		F0R(j, 100) {
			int idx = j % 10, siz = (j - idx) / 10;
			if (indeg[i][j] == 1) {
				bad_pairs.emplace_back(array<int,2>{siz, idx});
			}
			else if (indeg[i][j] > 1) {
				bad[siz][idx][siz][idx] = 1;
			}
		}

		for (int j = 0; j < sz(bad_pairs); ++j) {
			for (int k = j + 1; k < sz(bad_pairs); ++k) {
				auto &edge1 = bad_pairs[j], &edge2 = bad_pairs[k];
				bad[edge1[0]][edge1[1]][edge2[0]][edge2[1]] = 1;
				bad[edge2[0]][edge2[1]][edge1[0]][edge1[1]] = 1;
			}
		}
	}
	solve();
	cout << tot << newl;

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
const int N = 2e5+5;

int head[N],pre[N],id[N],w[N],ki=0;
void add(int a,int b,int c){
    pre[++ki] = head[a] , head[a] = ki , id[ki] = b , w[ki] = c;
}

vector<vector<int> > v(N);

int n,m,k;
int out[N];
int de[N];
bool is[110][110];
int ans = 0;

void dfs(int a){
    if(a==k){
        for(int i=1;i<=k;i++){
            for(int j=1;j<=k;j++){
                if(is[i*10+de[i]][j*10+de[j]]) return;
            }
        }
        ans++;
        return;
    }
    for(int i=1;i<=a+1;i++){
        de[a+1] = i;
        dfs(a+1);
    }
}

int main()
{
    ios::sync_with_stdio(false);

    cin>>n>>m>>k;
    for(int i=1;i<=m;i++){
        int a,b,c;  cin>>a>>b>>c;
        add(a,b,c);
        out[a]++;
    }
    for(int i=1;i<=n;i++){
        int cnt = 0,p;
        for(int j=head[i];j;j=pre[j])
            de[++cnt] = w[j];
        sort(de+1,de+cnt+1);
        for(int j=head[i];j;j=pre[j]){
            int to = id[j];
            for(p=1;p<=cnt;p++)
                if(w[j]==de[p]) break;
            v[to].push_back(out[i]*10+p);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<v[i].size();j++){
            for(int p=0;p<v[i].size();p++){
                if(p==j) continue;
                is[v[i][j]][v[i][p]] = 1;
            }
        }
    }
    dfs(0);
    cout<<ans<<endl;
}


#include "bits/stdc++.h"
using namespace std;
const int N = 2e5+5;

int head[N],pre[N],id[N],w[N],ki=0;
void add(int a,int b,int c){
    pre[++ki] = head[a] , head[a] = ki , id[ki] = b , w[ki] = c;
}

vector<vector<int> > v(N);

int n,m,k;
int out[N];
int de[N];
bool is[110][110];
int ans = 0;

void dfs(int a){
    if(a==k){
        for(int i=1;i<=k;i++){
            for(int j=1;j<=k;j++){
                if(is[i*10+de[i]][j*10+de[j]]) return;
            }
        }
        ans++;
        return;
    }
    for(int i=1;i<=a+1;i++){
        de[a+1] = i;
        dfs(a+1);
    }
}

int main()
{
    ios::sync_with_stdio(false);

    cin>>n>>m>>k;
    for(int i=1;i<=m;i++){
        int a,b,c;  cin>>a>>b>>c;
        add(a,b,c);
        out[a]++;
    }
    for(int i=1;i<=n;i++){
        int cnt = 0,p;
        for(int j=head[i];j;j=pre[j])
            de[++cnt] = w[j];
        sort(de+1,de+cnt+1);
        for(int j=head[i];j;j=pre[j]){
            int to = id[j];
            p = lower_bound(de+1,de+cnt+1,w[j]) - de;
            v[to].push_back(out[i]*10+p);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<v[i].size();j++){
            for(int p=0;p<v[i].size();p++){
                if(p==j) continue;
                is[v[i][j]][v[i][p]] = 1;
            }
        }
    }
    dfs(0);
    cout<<ans<<endl;
}


#include "bits/stdc++.h"
using namespace std;
const int N = 2e5+5;

int head[N],pre[N],id[N],w[N],ki=0;
void add(int a,int b,int c){
    pre[++ki] = head[a] , head[a] = ki , id[ki] = b , w[ki] = c;
}

vector<vector<int> > v(N);

int n,m,k;
int out[N];
int de[N];
bool is[110][110];
int ans = 0;

void dfs(int a){
    if(a==k){
        for(int i=1;i<=k;i++){
            for(int j=1;j<=k;j++){
                if(is[i*10+de[i]][j*10+de[j]]) return;
            }
        }
        ans++;
        return;
    }
    for(int i=1;i<=a+1;i++){
        de[a+1] = i;
        dfs(a+1);
    }
}

int main()
{
    ios::sync_with_stdio(false);

    cin>>n>>m>>k;
    for(int i=1;i<=m;i++){
        int a,b,c;  cin>>a>>b>>c;
        add(a,b,c);
        out[a]++;
    }
    for(int i=1;i<=n;i++){
        int cnt = 0,p;
        for(int j=head[i];j;j=pre[j])
            de[++cnt] = w[j];
        sort(de+1,de+cnt+1);
        for(int j=head[i];j;j=pre[j]){
            int to = id[j];
            p = lower_bound(de+1,de+cnt+1,w[j]) - de;
            v[to].push_back(out[i]*10+p);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<v[i].size();j++){
            for(int p=j+1;p<v[i].size();p++){
                is[v[i][j]][v[i][p]] = 1;
                is[v[i][p]][v[i][j]] = 1;
            }
        }
    }
    dfs(0);
    cout<<ans<<endl;
}


#include "bits/stdc++.h"
using namespace std;
const int N = 2e5+5;

int head[N],pre[N],id[N],w[N],ki=0;
void add(int a,int b,int c){
    pre[++ki] = head[a] , head[a] = ki , id[ki] = b , w[ki] = c;
}

set<int> v[N];

int n,m,k;
int out[N];
int de[N];
bool is[110][110];
int ans = 0;

void dfs(int a){
    if(a==k){
        for(int i=1;i<=k;i++){
            for(int j=1;j<=k;j++){
                if(is[i*10+de[i]][j*10+de[j]]) return;
            }
        }
        ans++;
        return;
    }
    for(int i=1;i<=a+1;i++){
        de[a+1] = i;
        dfs(a+1);
    }
}

int main()
{
    ios::sync_with_stdio(false);

    cin>>n>>m>>k;
    for(int i=1;i<=m;i++){
        int a,b,c;  cin>>a>>b>>c;
        add(a,b,c);
        out[a]++;
    }
    for(int i=1;i<=n;i++){
        int cnt = 0,p;
        for(int j=head[i];j;j=pre[j])
            de[++cnt] = w[j];
        sort(de+1,de+cnt+1);
        for(int j=head[i];j;j=pre[j]){
            int to = id[j];
            p = lower_bound(de+1,de+cnt+1,w[j]) - de;
            v[to].insert(out[i]*10+p);
        }
    }
    for(int i=1;i<=n;i++){
        for(auto x : v[i]){
            for(auto y : v[i]){
                if(x==y) continue;
                is[x][y] = 1;
            }
        }
    }
    dfs(0);
    cout<<ans<<endl;
}


#include "bits/stdc++.h"
using namespace std;
const int N = 2e5+5;

int head[N],pre[N],id[N],w[N],ki=0;
void add(int a,int b,int c){
    pre[++ki] = head[a] , head[a] = ki , id[ki] = b , w[ki] = c;
}

set<int> v[N];

int n,m,k;
int out[N];
int de[N];
bool is[110][110];
int use[N][110];
int ans = 0;

void dfs(int a){
    if(a==k){
        for(int i=1;i<=k;i++){
            for(int j=1;j<=k;j++){
                if(is[i*10+de[i]][j*10+de[j]]) return;
            }
        }
        ans++;
        return;
    }
    for(int i=1;i<=a+1;i++){
        de[a+1] = i;
        dfs(a+1);
    }
}

int main()
{
    ios::sync_with_stdio(false);

    cin>>n>>m>>k;
    for(int i=1;i<=m;i++){
        int a,b,c;  cin>>a>>b>>c;
        add(a,b,c);
        out[a]++;
    }
    for(int i=1;i<=n;i++){
        int cnt = 0,p;
        for(int j=head[i];j;j=pre[j])
            de[++cnt] = w[j];
        sort(de+1,de+cnt+1);
        for(int j=head[i];j;j=pre[j]){
            int to = id[j];
            p = lower_bound(de+1,de+cnt+1,w[j]) - de;
            v[to].insert(out[i]*10+p);
            use[to][out[i]*10+p]++;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=k;j++)
            for(int p=1;p<=j;p++)
                if(use[i][j*10+p]>1) is[j*10+p][j*10+p]=1;
        for(auto x : v[i]){
            for(auto y : v[i]){
                if(x==y) continue;
                is[x][y] = 1;
            }
        }
    }
    dfs(0);
    cout<<ans<<endl;
}


#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <unordered_set>
#include <sstream>
#include <cstring>
#include <iomanip>
#include <queue>
#include <unordered_map>
#include <random>
#include <cfloat>
#include <chrono>

int32_t answer = 0;
void enumerate(int32_t step, int32_t num_steps, int32_t* indegree, std::vector<int32_t>* graph,
		std::vector<int32_t>* per_outdegree) {
	for(int32_t i = 0; i < step; i++) {
		bool can_take = true;
		for(int32_t j = 0; j < per_outdegree[step].size(); j++) {
			indegree[graph[per_outdegree[step][j]][i]]++;
			if(indegree[graph[per_outdegree[step][j]][i]] >= 2) {
				//undo
				for(int32_t k = 0; k <= j; k++)
					indegree[graph[per_outdegree[step][k]][i]]--;
				can_take = false;
				break;
			}
		}
		if(can_take) {
			//call
			if(step == num_steps)
				answer++;
			else
				enumerate(step + 1, num_steps, indegree, graph, per_outdegree);

			//undo
			for(int32_t k = 0; k < per_outdegree[step].size(); k++)
				indegree[graph[per_outdegree[step][k]][i]]--;
		}
	}
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	int32_t n ,m, k;
	std::cin >> n >> m >> k;

	std::vector<std::pair<int32_t, int32_t> >* graph = new std::vector<std::pair<int32_t, int32_t> >[n];
	for(int32_t i = 0; i < m; i++) {
		int32_t src, dst, weight;
		std::cin >> src >> dst >> weight;
		src--;
		dst--;

		graph[src].emplace_back(weight, dst);
	}
	for(int32_t i = 0 ; i < n ; i++)
		std::sort(graph[i].begin(), graph[i].end());
	std::vector<int32_t>* graph2= new std::vector<int32_t>[n];
	for(int32_t i = 0 ; i < n; i++)
		for(int32_t j = 0 ; j < graph[i].size(); j++)
			graph2[i].push_back(graph[i][j].second);

	std::vector<int32_t> per_outdegree[10];
	for(int32_t i = 0; i < 10; i++)
		per_outdegree[i].reserve(n);
	for(int32_t i = 0 ; i < n ; i++) {
		per_outdegree[graph[i].size()].push_back(i);
	}

	int32_t* indegree = new int32_t[n];
	for(int32_t i = 0 ; i < n ; i++)
		indegree[i] = 0;
	enumerate(1, k, indegree, graph2, per_outdegree);

	std::cout << answer << "\n";
	return 0;
}


#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <unordered_set>
#include <sstream>
#include <cstring>
#include <iomanip>
#include <queue>
#include <unordered_map>
#include <random>
#include <cfloat>
#include <chrono>

std::map<std::pair<int32_t, int32_t>, std::set<std::pair<int32_t, int32_t> > > invalid;

bool compatible(std::pair<int32_t, int32_t> p1, std::pair<int32_t, int32_t> p2) {
	return invalid[p1].find(p2) == invalid[p1].end();
}

int32_t answer = 0;
void enumerate(int32_t step, int32_t num_steps, int32_t* choices) {
	for(int32_t i = 0; i < step; i++) {
		choices[step] = i;
		if(step == num_steps) {
			//valid?
			bool ok = true;
			for(int32_t j = 1; j <= num_steps; j++) {
				for(int32_t k = j; k <= num_steps; k++) {
					if(!compatible({j, choices[j]}, {k, choices[k]})) {
						ok = false;
						break;
					}
				}
			}
			if(ok)
				answer++;
		} else
			enumerate(step + 1, num_steps, choices);
	}
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	int32_t n ,m, k;
	std::cin >> n >> m >> k;

	std::vector<std::pair<int32_t, int32_t> >* graph = new std::vector<std::pair<int32_t, int32_t> >[n];
	for(int32_t i = 0; i < m; i++) {
		int32_t src, dst, weight;
		std::cin >> src >> dst >> weight;
		/*weight = i;
		src = i;
		dst = (i + 1) % n;*/
		src--;
		dst--;

		graph[src].emplace_back(weight, dst);
	}
	for(int32_t i = 0 ; i < n ; i++)
		std::sort(graph[i].begin(), graph[i].end());
	std::set<std::pair<int32_t, int32_t> >* incoming_types = new std::set<std::pair<int32_t, int32_t> >[n];
	for(int32_t i = 0 ; i < n ; i++) {
		for(int32_t j = 0; j < graph[i].size(); j++) {
			if (incoming_types[graph[i][j].second].find({graph[i].size(), j}) !=
				incoming_types[graph[i][j].second].end())
				invalid[{graph[i].size(), j}].emplace(graph[i].size(), j);

			incoming_types[graph[i][j].second].emplace(graph[i].size(), j);
		}
	}

	std::vector<int32_t> heavy;
	for(int32_t z = 0 ; z  < n ;z++)
		if(incoming_types[z].size() > 20)
			heavy.push_back(z);
		else {
			for(int32_t i = 1; i <= k; i++)
				for(int32_t j = 0; j < i; j++)
					for(int32_t p = i; p <= k; p++)
						for(int32_t q = 0; q < p; q++) {
							if(incoming_types[z].find({i, j}) != incoming_types[z].end() && incoming_types[z].find({p, q}) != incoming_types[z].end())
								if(i != p || j != q)
									invalid[{i, j}].emplace(p, q);
						}
		}

	for(int32_t i = 1; i <= k; i++)
		for(int32_t j = 0; j < i; j++)
			for(int32_t p = i; p <= k; p++)
				for(int32_t q = 0; q < p; q++) {
					for(int32_t v = 0; v < heavy.size(); v++)
						if(incoming_types[heavy[v]].find({i, j}) != incoming_types[heavy[v]].end() && incoming_types[heavy[v]].find({p, q}) != incoming_types[heavy[v]].end())
							if(i != p || j != q)
								invalid[{i, j}].emplace(p, q);
				}

	int32_t* choices = new int32_t[k + 1];
	enumerate(1, k, choices);

	std::cout << answer << "\n";
	return 0;
}


#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <unordered_set>
#include <sstream>
#include <cstring>
#include <iomanip>
#include <queue>
#include <unordered_map>
#include <random>
#include <cfloat>
#include <chrono>

int32_t answer = 0;
void enumerate(int32_t step, int32_t num_steps, int32_t* indegree, std::vector<std::pair<int32_t, int32_t> >* graph,
		std::vector<int32_t>* per_outdegree) {
	for(int32_t i = 0; i < step; i++) {
		bool can_take = true;
		for(int32_t j = 0; j < per_outdegree[step].size(); j++) {
			indegree[graph[per_outdegree[step][j]][i].second]++;
			if(indegree[graph[per_outdegree[step][j]][i].second] >= 2) {
				//undo
				for(int32_t k = 0; k <= j; k++)
					indegree[graph[per_outdegree[step][k]][i].second]--;
				can_take = false;
				break;
			}
		}
		if(can_take) {
			//call
			if(step == num_steps)
				answer++;
			else
				enumerate(step + 1, num_steps, indegree, graph, per_outdegree);

			//undo
			for(int32_t k = 0; k - per_outdegree[step].size(); k++)
				indegree[graph[per_outdegree[step][k]][i].second]--;
		}
	}
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	int32_t n ,m, k;
	std::cin >> n >> m >> k;

	std::vector<std::pair<int32_t, int32_t> >* graph = new std::vector<std::pair<int32_t, int32_t> >[n];
	for(int32_t i = 0; i < m; i++) {
		int32_t src, dst, weight;
		std::cin >> src >> dst >> weight;
		src--;
		dst--;

		graph[src].emplace_back(weight, dst);
	}
	for(int32_t i = 0 ; i < n  ;i++)
		std::sort(graph[i].begin(), graph[i].end());

	std::vector<int32_t> per_outdegree[10];
	for(int32_t i = 0 ; i < n ; i++) {
		per_outdegree[graph[i].size()].push_back(i);
	}

	int32_t* indegree = new int32_t[n];
	for(int32_t i = 0 ; i < n ; i++)
		indegree[i] = 0;
	enumerate(1, k, indegree, graph, per_outdegree);

	std::cout << answer << "\n";
	return 0;
}


#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <unordered_set>
#include <sstream>
#include <cstring>
#include <iomanip>
#include <queue>
#include <unordered_map>
#include <random>
#include <cfloat>
#include <chrono>

std::map<std::pair<int32_t, int32_t>, std::set<std::pair<int32_t, int32_t> > > invalid;

bool compatible(std::pair<int32_t, int32_t> p1, std::pair<int32_t, int32_t> p2) {
	return invalid[p1].find(p2) == invalid[p1].end();
}

int32_t answer = 0;
void enumerate(int32_t step, int32_t num_steps, int32_t* choices) {
	for(int32_t i = 0; i < step; i++) {
		choices[step] = i;
		if(step == num_steps) {
			//valid?
			bool ok = true;
			for(int32_t j = 1; j <= num_steps; j++) {
				for(int32_t k = j; k <= num_steps; k++) {
					if(!compatible({j, choices[j]}, {k, choices[k]})) {
						ok = false;
						break;
					}
				}
			}
			if(ok)
				answer++;
		} else
			enumerate(step + 1, num_steps, choices);
	}
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	int32_t n ,m, k;
	std::cin >> n >> m >> k;

	std::vector<std::pair<int32_t, int32_t> >* graph = new std::vector<std::pair<int32_t, int32_t> >[n];
	for(int32_t i = 0; i < m; i++) {
		int32_t src, dst, weight;
		std::cin >> src >> dst >> weight;
		/*weight = i;
		src = i / 9;
		dst = (i / 9 + i % 9) % n;*/
		src--;
		dst--;

		graph[src].emplace_back(weight, dst);
	}
	for(int32_t i = 0 ; i < n ; i++)
		std::sort(graph[i].begin(), graph[i].end());
	std::set<std::pair<int32_t, int32_t> >* incoming_types = new std::set<std::pair<int32_t, int32_t> >[n];
	for(int32_t i = 0 ; i < n ; i++) {
		for(int32_t j = 0; j < graph[i].size(); j++) {
			if (incoming_types[graph[i][j].second].find({graph[i].size(), j}) !=
				incoming_types[graph[i][j].second].end())
					invalid[{graph[i].size(), j}].emplace(graph[i].size(), j);

			incoming_types[graph[i][j].second].emplace(graph[i].size(), j);
		}
	}

	for(int32_t i = 1; i <= k; i++)
		for(int32_t j = 0; j < i; j++)
			for(int32_t p = i; p <= k; p++)
				for(int32_t q = 0; q < p; q++) {
					for(int32_t v = 0; v < n; v++)
						if(incoming_types[v].find({i, j}) != incoming_types[v].end() && incoming_types[v].find({p, q}) != incoming_types[v].end())
							if(i != p || j != q)
								invalid[{i, j}].emplace(p, q);
				}

	int32_t* choices = new int32_t[k + 1];
	enumerate(1, k, choices);

	std::cout << answer << "\n";
	return 0;
}


#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <unordered_set>
#include <sstream>
#include <cstring>
#include <iomanip>
#include <queue>
#include <unordered_map>
#include <random>
#include <cfloat>
#include <chrono>

std::map<std::pair<int32_t, int32_t>, std::set<std::pair<int32_t, int32_t> > > invalid;

bool compatible(std::pair<int32_t, int32_t> p1, std::pair<int32_t, int32_t> p2) {
	return invalid[p1].find(p2) == invalid[p1].end();
}

int32_t answer = 0;
void enumerate(int32_t step, int32_t num_steps, int32_t* choices) {
	for(int32_t i = 0; i < step; i++) {
		choices[step] = i;
		if(step == num_steps) {
			//valid?
			bool ok = true;
			for(int32_t j = 1; j <= num_steps; j++) {
				for(int32_t k = j; k <= num_steps; k++) {
					if(!compatible({j, choices[j]}, {k, choices[k]})) {
						ok = false;
						break;
					}
				}
			}
			if(ok)
				answer++;
		} else
			enumerate(step + 1, num_steps, choices);
	}
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	int32_t n ,m, k;
	std::cin >> n >> m >> k;

	std::vector<std::pair<int32_t, int32_t> >* graph = new std::vector<std::pair<int32_t, int32_t> >[n];
	for(int32_t i = 0; i < m; i++) {
		int32_t src, dst, weight;
		std::cin >> src >> dst >> weight;
		/*weight = i;
		src = i / 9;
		dst = (i / 9 + i % 9) % n;*/
		src--;
		dst--;

		graph[src].emplace_back(weight, dst);
	}
	for(int32_t i = 0 ; i < n ; i++)
		std::sort(graph[i].begin(), graph[i].end());
	std::set<std::pair<int32_t, int32_t> >* incoming_types = new std::set<std::pair<int32_t, int32_t> >[n];
	for(int32_t i = 0 ; i < n ; i++) {
		for(int32_t j = 0; j < graph[i].size(); j++) {
			if (incoming_types[graph[i][j].second].find({graph[i].size(), j}) !=
				incoming_types[graph[i][j].second].end())
				invalid[{graph[i].size(), j}].emplace(graph[i].size(), j);

			incoming_types[graph[i][j].second].emplace(graph[i].size(), j);
		}
	}

	for(int32_t i = 1; i <= k; i++)
		for(int32_t j = 0; j < i; j++) {
			for(int32_t v = 0; v < n; v++)
				if(incoming_types[v].find({i, j}) != incoming_types[v].end())
					for(int32_t p = i; p <= k; p++)
						for(int32_t q = 0; q < p; q++) {
								if(incoming_types[v].find({p, q}) != incoming_types[v].end())
									if(i != p || j != q)
										invalid[{i, j}].emplace(p, q);
						}
					}

	int32_t* choices = new int32_t[k + 1];
	enumerate(1, k, choices);

	std::cout << answer << "\n";
	return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define pll pair <ll, ll>
#define mp make_pair
#define pyshnapyshnakaa ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define x first
#define y second
#pragma GCC optimize("O3")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
#define plll pair <pair <ll, ll>, ll>
#define pllll pair <pair <ll, ll>, pair <ll, ll> >
#define psl pair <string, ll>
#define pld pair <ld, ld>
#define all(a) a.begin(), a.end()
#define vvl vector <vector <ll> >

typedef int ll;

typedef long double ld;

using namespace std;

const ll maxn = 1e6;
const ll maxk = 12;

ll n, m, k, t;

// ll C[maxn];

vector <pll> V[maxn];

vector <ll> vers[maxk];

// ll to[maxn];

// ll cnt0 = 0;

set <ll> S[maxk][maxk];

vector <pll> CS[maxn];

map <pll, vector <pll>> F;

set <pll> bad;

map <pll, ll> C;

// vector <ll> I;

ll find_ans(ll i) {
    if (i == k + 1) {
        // for (auto i : I) {
        //     cout << i << " ";
        // }
        // cout << endl;
        return 1;
    }
    ll ans = 0;
    // cout << i << " I" << endl;
    ll q;
    for (q = 0; q < i; q++) {
        pll p1 = {i, q};
        // cout
        // cout << F[p1].size() << endl;
        if (bad.find(p1) != bad.end()) {
            continue;
        }
        if (i == k) {
            ans++;
            continue;
        }
        for (auto p : F[p1]) {
            C[p]++;
            if (C[p] == 1) {
                bad.insert(p);
            }
        }
        if (bad.find(p1) == bad.end()) {
            // I.pb(q);
            ans += find_ans(i + 1);
            // I.pop_back();
            // continue;
        }
        for (auto p : F[p1]) {
            C[p]--;
            if (C[p] == 0) {
                bad.erase(p);
            }
        }
    }
    return ans;
}

int main() {
    pyshnapyshnakaa;
    ll q, w, e, a, b, c;
    cin >> n >> m >> k;
    for (q = 0; q < m; q++) {
        cin >> a >> b >> c;
        a--; b--;
        V[a].pb(mp(c, b));
    }
    for (q = 0; q < n; q++) {
        sort(all(V[q]));
    }
    for (q = 0; q < n; q++) {
        // to[q] = -1;
        vers[V[q].size()].pb(q);
    }
    // cnt0 = n;
    for (q = 1; q <= k; q++) {
        for (w = 0; w < q; w++) {
        // cout << "Q " <<  q << " " << vers[q].size() << endl;
            for (auto v : vers[q]) {
                // cout << q << " " << w << endl;
    // cout << "FALL" << endl;
                // cout << q << " " << w << " " << v << " " << V[v].size() << endl;
                // S[q][w].insert(V[v][w].second);
                CS[V[v][w].second].pb(mp(q, w));
            }
        }
    }
    // for (auto v : S[1][0]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[2][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[3][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[4][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    for (q = 0; q < n; q++) {
        for (int i = 0; i < CS[q].size(); i++) {
            for (int j = i + 1; j < CS[q].size(); j++) {
                pll p1 = CS[q][i], p2 = CS[q][j];
                F[p1].pb(p2);
                F[p2].pb(p1);
                // cout << p1.first << " " << p1.second << " P " << p2.first << " " << p2.second << endl;
            }
        }
    }
    ll ans = find_ans(1);
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define pll pair <ll, ll>
#define mp make_pair
#define pyshnapyshnakaa ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define x first
#define y second
#pragma GCC optimize("O3")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
#define plll pair <pair <ll, ll>, ll>
#define pllll pair <pair <ll, ll>, pair <ll, ll> >
#define psl pair <string, ll>
#define pld pair <ld, ld>
#define all(a) a.begin(), a.end()
#define vvl vector <vector <ll> >

typedef int ll;

typedef long double ld;

using namespace std;

const ll maxn = 1e6;
const ll maxk = 12;

ll n, m, k, t;

// ll C[maxn];

vector <pll> V[maxn];

vector <ll> vers[maxk];

// ll to[maxn];

// ll cnt0 = 0;

set <ll> S[maxk][maxk];

vector <pll> CS[maxn];

set <pll> F[maxk][maxk];

// set <pll> bad;

set <pll> very_bad;

map <pll, ll> C;

vector <ll> I;

set <pll> SS[maxn];

ll find_ans(ll i) {
    // if (i == k + 1) {
    //     // for (auto i : I) {
    //     //     cout << i << " ";
    //     // }
    //     // cout << endl;
    //     return 1;
    // }
    ll ans = 0;
    // cout << i << " I" << endl;
    ll q;
    for (q = 0; q < i; q++) {
        pll p1 = {i, q};
        // cout
        // cout << F[p1].size() << endl;
        if (very_bad.find(p1) != very_bad.end()) {
            continue;
        }
        bool fail = 0;
        for (auto p : F[p1.first][p1.second]) {
            ll ind = p.first - 1;
            // cout << ind << " " <<
            assert(ind < I.size());
            if (I[ind] == p.second) {
                fail = 1;
                break;
            }
        }
        if (fail) {
            continue;
        }
        // for ()
        if (i == k) {
            // if (very_bad.find(p1) == very_bad.end()) {
            ans++;
            continue;
        }
        // if (/*bad.find(p1) == bad.end()*/) {
        I.pb(q);
        ans += find_ans(i + 1);
        I.pop_back();
            // continue;
        // }
    }
    return ans;
}

int main() {
    pyshnapyshnakaa;
    ll q, w, e, a, b, c;
    cin >> n >> m >> k;
    for (q = 0; q < m; q++) {
        cin >> a >> b >> c;
        a--; b--;
        V[a].pb(mp(c, b));
    }
    for (q = 0; q < n; q++) {
        sort(all(V[q]));
    }
    for (q = 0; q < n; q++) {
        // to[q] = -1;
        vers[V[q].size()].pb(q);
    }
    // cnt0 = n;
    for (q = 1; q <= k; q++) {
        for (w = 0; w < q; w++) {
        // cout << "Q " <<  q << " " << vers[q].size() << endl;
            for (auto v : vers[q]) {
                // cout << q << " " << w << endl;
    // cout << "FALL" << endl;
                // cout << q << " " << w << " " << v << " " << V[v].size() << endl;
                // S[q][w].insert(V[v][w].second);
                if (SS[V[v][w].second].find(mp(q, w)) != SS[V[v][w].second].end()) {
                    very_bad.insert(mp(q, w));
                    continue;
                }
                SS[V[v][w].second].insert(mp(q, w));
                CS[V[v][w].second].pb(mp(q, w));
            }
        }
    }
    // for (auto v : S[1][0]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[2][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[3][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[4][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    for (q = 0; q < n; q++) {
        for (int i = 0; i < CS[q].size(); i++) {
            for (int j = i + 1; j < CS[q].size(); j++) {
                pll p1 = CS[q][i], p2 = CS[q][j];
                if (p1.first > p2.first) {
                    F[p1.first][p1.second].insert(p2);
                }
                // else {
                if (p2.first > p1.first) {
                    F[p2.first][p2.second].insert(p1);
                }
                // cout << p1.first << " " << p1.second << " P " << p2.first << " " << p2.second << endl;
            }
        }
    }
    // cout << "START " << endl;
    ll ans = find_ans(1);
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define pll pair <ll, ll>
#define mp make_pair
#define pyshnapyshnakaa ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define x first
#define y second
#pragma GCC optimize("O3")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
#define plll pair <pair <ll, ll>, ll>
#define pllll pair <pair <ll, ll>, pair <ll, ll> >
#define psl pair <string, ll>
#define pld pair <ld, ld>
#define all(a) a.begin(), a.end()
#define vvl vector <vector <ll> >

typedef long long ll;

typedef long double ld;

using namespace std;

const ll maxn = 1e6;
const ll maxk = 12;

ll n, m, k, t;

// ll C[maxn];

vector <pll> V[maxn];

vector <ll> vers[maxk];

// ll to[maxn];

// ll cnt0 = 0;

set <ll> S[maxk][maxk];

vector <pll> CS[maxn];

map <pll, vector <pll>> F;

set <pll> bad;

set <pll> very_bad;

map <pll, ll> C;

// vector <ll> I;

ll find_ans(ll i) {
    // if (i == k + 1) {
    //     // for (auto i : I) {
    //     //     cout << i << " ";
    //     // }
    //     // cout << endl;
    //     return 1;
    // }
    ll ans = 0;
    // cout << i << " I" << endl;
    ll q;
    for (q = 0; q < i; q++) {
        pll p1 = {i, q};
        // cout
        // cout << F[p1].size() << endl;
        if (bad.find(p1) != bad.end()) {
            continue;
        }
        if (i == k) {
            if (very_bad.find(p1) == very_bad.end()) {
                ans++;
            }
            continue;
        }
        for (auto p : F[p1]) {
            C[p]++;
            if (C[p] == 1) {
                bad.insert(p);
            }
        }
        if (bad.find(p1) == bad.end()) {
            // I.pb(q);
            ans += find_ans(i + 1);
            // I.pop_back();
            // continue;
        }
        for (auto p : F[p1]) {
            C[p]--;
            if (C[p] == 0) {
                bad.erase(p);
            }
        }
    }
    return ans;
}

int main() {
    pyshnapyshnakaa;
    ll q, w, e, a, b, c;
    cin >> n >> m >> k;
    for (q = 0; q < m; q++) {
        cin >> a >> b >> c;
        a--; b--;
        V[a].pb(mp(c, b));
    }
    for (q = 0; q < n; q++) {
        sort(all(V[q]));
    }
    for (q = 0; q < n; q++) {
        // to[q] = -1;
        vers[V[q].size()].pb(q);
    }
    // cnt0 = n;
    for (q = 1; q <= k; q++) {
        for (w = 0; w < q; w++) {
        // cout << "Q " <<  q << " " << vers[q].size() << endl;
            for (auto v : vers[q]) {
                // cout << q << " " << w << endl;
    // cout << "FALL" << endl;
                // cout << q << " " << w << " " << v << " " << V[v].size() << endl;
                // S[q][w].insert(V[v][w].second);
                CS[V[v][w].second].pb(mp(q, w));
            }
        }
    }
    // for (auto v : S[1][0]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[2][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[3][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[4][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    for (q = 0; q < n; q++) {
        for (int i = 0; i < CS[q].size(); i++) {
            for (int j = i + 1; j < CS[q].size(); j++) {
                pll p1 = CS[q][i], p2 = CS[q][j];
                if (p1 == p2) {
                    very_bad.insert(p1);
                }
                if (p1.first <= p2.first) {
                    F[p1].pb(p2);
                }
                else {
                    F[p2].pb(p1);
                }
                // cout << p1.first << " " << p1.second << " P " << p2.first << " " << p2.second << endl;
            }
        }
    }
    ll ans = find_ans(1);
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define pll pair <ll, ll>
#define mp make_pair
#define pyshnapyshnakaa ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define x first
#define y second
#pragma GCC optimize("O3")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
#define plll pair <pair <ll, ll>, ll>
#define pllll pair <pair <ll, ll>, pair <ll, ll> >
#define psl pair <string, ll>
#define pld pair <ld, ld>
#define all(a) a.begin(), a.end()
#define vvl vector <vector <ll> >

typedef int ll;

typedef long double ld;

using namespace std;

const ll maxn = 1e6;
const ll maxk = 12;

ll n, m, k, t;

// ll C[maxn];

vector <pll> V[maxn];

vector <ll> vers[maxk];

// ll to[maxn];

// ll cnt0 = 0;

set <ll> S[maxk][maxk];

vector <pll> CS[maxn];

map <pll, set <pll> > F;

// set <pll> bad;

set <pll> very_bad;

map <pll, ll> C;

vector <ll> I;

ll find_ans(ll i) {
    // if (i == k + 1) {
    //     // for (auto i : I) {
    //     //     cout << i << " ";
    //     // }
    //     // cout << endl;
    //     return 1;
    // }
    ll ans = 0;
    // cout << i << " I" << endl;
    ll q;
    for (q = 0; q < i; q++) {
        pll p1 = {i, q};
        // cout
        // cout << F[p1].size() << endl;
        if (very_bad.find(p1) != very_bad.end()) {
            continue;
        }
        bool fail = 0;
        for (auto p : F[p1]) {
            ll ind = p.first - 1;
            // cout << ind << " " <<
            assert(ind < I.size());
            if (I[ind] == p.second) {
                fail = 1;
                break;
            }
        }
        if (fail) {
            continue;
        }
        // for ()
        if (i == k) {
            // if (very_bad.find(p1) == very_bad.end()) {
            ans++;
            continue;
        }
        // if (/*bad.find(p1) == bad.end()*/) {
        I.pb(q);
        ans += find_ans(i + 1);
        I.pop_back();
            // continue;
        // }
    }
    return ans;
}

int main() {
    pyshnapyshnakaa;
    ll q, w, e, a, b, c;
    cin >> n >> m >> k;
    for (q = 0; q < m; q++) {
        cin >> a >> b >> c;
        a--; b--;
        V[a].pb(mp(c, b));
    }
    for (q = 0; q < n; q++) {
        sort(all(V[q]));
    }
    for (q = 0; q < n; q++) {
        // to[q] = -1;
        vers[V[q].size()].pb(q);
    }
    // cnt0 = n;
    for (q = 1; q <= k; q++) {
        for (w = 0; w < q; w++) {
        // cout << "Q " <<  q << " " << vers[q].size() << endl;
            for (auto v : vers[q]) {
                // cout << q << " " << w << endl;
    // cout << "FALL" << endl;
                // cout << q << " " << w << " " << v << " " << V[v].size() << endl;
                // S[q][w].insert(V[v][w].second);
                CS[V[v][w].second].pb(mp(q, w));
            }
        }
    }
    // for (auto v : S[1][0]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[2][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[3][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[4][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    for (q = 0; q < n; q++) {
        for (int i = 0; i < CS[q].size(); i++) {
            for (int j = i + 1; j < CS[q].size(); j++) {
                pll p1 = CS[q][i], p2 = CS[q][j];
                if (p1 == p2) {
                    very_bad.insert(p1);
                }
                if (p1.first > p2.first) {
                    F[p1].insert(p2);
                }
                // else {
                if (p2.first > p1.first) {
                    F[p2].insert(p1);
                }
                // cout << p1.first << " " << p1.second << " P " << p2.first << " " << p2.second << endl;
            }
        }
    }
    ll ans = find_ans(1);
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define pll pair <ll, ll>
#define mp make_pair
#define pyshnapyshnakaa ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define x first
#define y second
#pragma GCC optimize("O3")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
#define plll pair <pair <ll, ll>, ll>
#define pllll pair <pair <ll, ll>, pair <ll, ll> >
#define psl pair <string, ll>
#define pld pair <ld, ld>
#define all(a) a.begin(), a.end()
#define vvl vector <vector <ll> >

typedef long long ll;

typedef long double ld;

using namespace std;

const ll maxn = 1e6;
const ll maxk = 12;

ll n, m, k, t;

ll C[maxn];

vector <pll> V[maxn];

vector <ll> vers[maxk];

ll to[maxn];

ll cnt0 = 0;

ll find_ans(ll i) {
    ll ans = 0;
    // cout << i << " I" << endl;
    if (i == k + 1) {
        // cout << cnt0 << endl;
        if (cnt0 == 0) {
            return 1;
        }
        return 0;
    }
    ll q;
    for (q = 0; q < i; q++) {
        for (auto v : vers[i]) {
            if (to[v] != -1) {
                ll v1 = to[v];
                C[v1]--;
                if (C[v1] == 0) {
                    cnt0++;
                }
            }
            to[v] = V[v][q].second;
            C[to[v]]++;
            if (C[to[v]] == 1) {
                cnt0--;
            }
        }
        // cout << "CALL " << i << " " <<
        ans += find_ans(i + 1);
    }
    return ans;
}

int main() {
    pyshnapyshnakaa;
    ll q, w, e, a, b, c;
    cin >> n >> m >> k;
    for (q = 0; q < m; q++) {
        cin >> a >> b >> c;
        a--; b--;
        V[a].pb(mp(c, b));
    }
    for (q = 0; q < n; q++) {
        sort(all(V[q]));
    }
    for (q = 0; q < n; q++) {
        to[q] = -1;
        vers[V[q].size()].pb(q);
    }
    cnt0 = n;
    ll ans = find_ans(1);
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define pll pair <ll, ll>
#define mp make_pair
#define pyshnapyshnakaa ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define x first
#define y second
#pragma GCC optimize("O3")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
#define plll pair <pair <ll, ll>, ll>
#define pllll pair <pair <ll, ll>, pair <ll, ll> >
#define psl pair <string, ll>
#define pld pair <ld, ld>
#define all(a) a.begin(), a.end()
#define vvl vector <vector <ll> >

typedef int ll;

typedef long double ld;

using namespace std;

const ll maxn = 1e6;
const ll maxk = 12;

ll n, m, k, t;

// ll C[maxn];

vector <pll> V[maxn];

vector <ll> vers[maxk];

// ll to[maxn];

// ll cnt0 = 0;

set <ll> S[maxk][maxk];

vector <pll> CS[maxn];

set <pll> F[maxk][maxk];

// set <pll> bad;

set <pll> very_bad;

map <pll, ll> C;

vector <ll> I;

set <pll> SS[maxn];

ll find_ans(ll i) {
    // if (i == k + 1) {
    //     // for (auto i : I) {
    //     //     cout << i << " ";
    //     // }
    //     // cout << endl;
    //     return 1;
    // }
    ll ans = 0;
    // cout << i << " I" << endl;
    ll q;
    for (q = 0; q < i; q++) {
        pll p1 = {i, q};
        // cout
        // cout << F[p1].size() << endl;
        if (very_bad.find(p1) != very_bad.end()) {
            continue;
        }
        bool fail = 0;
        for (auto p : F[p1.first][p1.second]) {
            ll ind = p.first - 1;
            // cout << ind << " " <<
            assert(ind < I.size());
            if (I[ind] == p.second) {
                fail = 1;
                break;
            }
        }
        if (fail) {
            continue;
        }
        // for ()
        if (i == k) {
            // if (very_bad.find(p1) == very_bad.end()) {
            ans++;
            continue;
        }
        // if (/*bad.find(p1) == bad.end()*/) {
        I.pb(q);
        ans += find_ans(i + 1);
        I.pop_back();
            // continue;
        // }
    }
    return ans;
}

int main() {
    pyshnapyshnakaa;
    ll q, w, e, a, b, c;
    cin >> n >> m >> k;
    for (q = 0; q < m; q++) {
        cin >> a >> b >> c;
        a--; b--;
        V[a].pb(mp(c, b));
    }
    for (q = 0; q < n; q++) {
        sort(all(V[q]));
    }
    for (q = 0; q < n; q++) {
        // to[q] = -1;
        vers[V[q].size()].pb(q);
    }
    // cnt0 = n;
    for (q = 1; q <= k; q++) {
        for (w = 0; w < q; w++) {
        // cout << "Q " <<  q << " " << vers[q].size() << endl;
            for (auto v : vers[q]) {
                // cout << q << " " << w << endl;
    // cout << "FALL" << endl;
                // cout << q << " " << w << " " << v << " " << V[v].size() << endl;
                // S[q][w].insert(V[v][w].second);
                if (SS[V[v][w].second].find(mp(q, w)) != SS[V[v][w].second].end()) {
                    continue;
                }
                SS[V[v][w].second].insert(mp(q, w));
                CS[V[v][w].second].pb(mp(q, w));
            }
        }
    }
    // for (auto v : S[1][0]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[2][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[3][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[4][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    for (q = 0; q < n; q++) {
        for (int i = 0; i < CS[q].size(); i++) {
            for (int j = i + 1; j < CS[q].size(); j++) {
                pll p1 = CS[q][i], p2 = CS[q][j];
                if (p1 == p2) {
                    very_bad.insert(p1);
                }
                if (p1.first > p2.first) {
                    F[p1.first][p1.second].insert(p2);
                }
                // else {
                if (p2.first > p1.first) {
                    F[p2.first][p2.second].insert(p1);
                }
                // cout << p1.first << " " << p1.second << " P " << p2.first << " " << p2.second << endl;
            }
        }
    }
    // cout << "START " << endl;
    ll ans = find_ans(1);
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define pll pair <ll, ll>
#define mp make_pair
#define pyshnapyshnakaa ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define x first
#define y second
#pragma GCC optimize("O3")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
#define plll pair <pair <ll, ll>, ll>
#define pllll pair <pair <ll, ll>, pair <ll, ll> >
#define psl pair <string, ll>
#define pld pair <ld, ld>
#define all(a) a.begin(), a.end()
#define vvl vector <vector <ll> >

typedef long long ll;

typedef long double ld;

using namespace std;

const ll maxn = 1e6;
const ll maxk = 12;

ll n, m, k, t;

// ll C[maxn];

vector <pll> V[maxn];

vector <ll> vers[maxk];

// ll to[maxn];

// ll cnt0 = 0;

set <ll> S[maxk][maxk];

vector <pll> CS[maxn];

map <pll, vector <pll>> F;

set <pll> bad;

map <pll, ll> C;

// vector <ll> I;

ll find_ans(ll i) {
    if (i == k + 1) {
        // for (auto i : I) {
        //     cout << i << " ";
        // }
        // cout << endl;
        return 1;
    }
    ll ans = 0;
    // cout << i << " I" << endl;
    ll q;
    for (q = 0; q < i; q++) {
        pll p1 = {i, q};
        // cout
        // cout << F[p1].size() << endl;
        if (bad.find(p1) != bad.end()) {
            continue;
        }
        for (auto p : F[p1]) {
            C[p]++;
            if (C[p] == 1) {
                bad.insert(p);
            }
        }
        if (bad.find(p1) == bad.end()) {
            // I.pb(q);
            ans += find_ans(i + 1);
            // I.pop_back();
            // continue;
        }
        for (auto p : F[p1]) {
            C[p]--;
            if (C[p] == 0) {
                bad.erase(p);
            }
        }
    }
    return ans;
}

int main() {
    pyshnapyshnakaa;
    ll q, w, e, a, b, c;
    cin >> n >> m >> k;
    for (q = 0; q < m; q++) {
        cin >> a >> b >> c;
        a--; b--;
        V[a].pb(mp(c, b));
    }
    for (q = 0; q < n; q++) {
        sort(all(V[q]));
    }
    for (q = 0; q < n; q++) {
        // to[q] = -1;
        vers[V[q].size()].pb(q);
    }
    // cnt0 = n;
    for (q = 1; q <= k; q++) {
        for (w = 0; w < q; w++) {
        // cout << "Q " <<  q << " " << vers[q].size() << endl;
            for (auto v : vers[q]) {
                // cout << q << " " << w << endl;
    // cout << "FALL" << endl;
                // cout << q << " " << w << " " << v << " " << V[v].size() << endl;
                // S[q][w].insert(V[v][w].second);
                CS[V[v][w].second].pb(mp(q, w));
            }
        }
    }
    // for (auto v : S[1][0]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[2][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[3][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[4][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    for (q = 0; q < n; q++) {
        for (int i = 0; i < CS[q].size(); i++) {
            for (int j = i + 1; j < CS[q].size(); j++) {
                pll p1 = CS[q][i], p2 = CS[q][j];
                F[p1].pb(p2);
                F[p2].pb(p1);
                // cout << p1.first << " " << p1.second << " P " << p2.first << " " << p2.second << endl;
            }
        }
    }
    ll ans = find_ans(1);
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define pll pair <ll, ll>
#define mp make_pair
#define pyshnapyshnakaa ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define x first
#define y second
#pragma GCC optimize("O3")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
#define plll pair <pair <ll, ll>, ll>
#define pllll pair <pair <ll, ll>, pair <ll, ll> >
#define psl pair <string, ll>
#define pld pair <ld, ld>
#define all(a) a.begin(), a.end()
#define vvl vector <vector <ll> >

typedef int ll;

typedef long double ld;

using namespace std;

const ll maxn = 1e6;
const ll maxk = 12;

ll n, m, k, t;

// ll C[maxn];

vector <pll> V[maxn];

vector <ll> vers[maxk];

// ll to[maxn];

// ll cnt0 = 0;

set <ll> S[maxk][maxk];

vector <pll> CS[maxn];

set <pll> F[maxk][maxk];

// set <pll> bad;

set <pll> very_bad;

map <pll, ll> C;

vector <ll> I;

ll find_ans(ll i) {
    // if (i == k + 1) {
    //     // for (auto i : I) {
    //     //     cout << i << " ";
    //     // }
    //     // cout << endl;
    //     return 1;
    // }
    ll ans = 0;
    // cout << i << " I" << endl;
    ll q;
    for (q = 0; q < i; q++) {
        pll p1 = {i, q};
        // cout
        // cout << F[p1].size() << endl;
        if (very_bad.find(p1) != very_bad.end()) {
            continue;
        }
        bool fail = 0;
        for (auto p : F[p1.first][p1.second]) {
            ll ind = p.first - 1;
            // cout << ind << " " <<
            assert(ind < I.size());
            if (I[ind] == p.second) {
                fail = 1;
                break;
            }
        }
        if (fail) {
            continue;
        }
        // for ()
        if (i == k) {
            // if (very_bad.find(p1) == very_bad.end()) {
            ans++;
            continue;
        }
        // if (/*bad.find(p1) == bad.end()*/) {
        I.pb(q);
        ans += find_ans(i + 1);
        I.pop_back();
            // continue;
        // }
    }
    return ans;
}

int main() {
    pyshnapyshnakaa;
    ll q, w, e, a, b, c;
    cin >> n >> m >> k;
    for (q = 0; q < m; q++) {
        cin >> a >> b >> c;
        a--; b--;
        V[a].pb(mp(c, b));
    }
    for (q = 0; q < n; q++) {
        sort(all(V[q]));
    }
    for (q = 0; q < n; q++) {
        // to[q] = -1;
        vers[V[q].size()].pb(q);
    }
    // cnt0 = n;
    for (q = 1; q <= k; q++) {
        for (w = 0; w < q; w++) {
        // cout << "Q " <<  q << " " << vers[q].size() << endl;
            for (auto v : vers[q]) {
                // cout << q << " " << w << endl;
    // cout << "FALL" << endl;
                // cout << q << " " << w << " " << v << " " << V[v].size() << endl;
                // S[q][w].insert(V[v][w].second);
                CS[V[v][w].second].pb(mp(q, w));
            }
        }
    }
    // for (auto v : S[1][0]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[2][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[3][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[4][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    for (q = 0; q < n; q++) {
        for (int i = 0; i < CS[q].size(); i++) {
            for (int j = i + 1; j < CS[q].size(); j++) {
                pll p1 = CS[q][i], p2 = CS[q][j];
                if (p1 == p2) {
                    very_bad.insert(p1);
                }
                if (p1.first > p2.first) {
                    F[p1.first][p1.second].insert(p2);
                }
                // else {
                if (p2.first > p1.first) {
                    F[p2.first][p2.second].insert(p1);
                }
                // cout << p1.first << " " << p1.second << " P " << p2.first << " " << p2.second << endl;
            }
        }
    }
    ll ans = find_ans(1);
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define pll pair <ll, ll>
#define mp make_pair
#define pyshnapyshnakaa ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define x first
#define y second
#pragma GCC optimize("O3")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
#define plll pair <pair <ll, ll>, ll>
#define pllll pair <pair <ll, ll>, pair <ll, ll> >
#define psl pair <string, ll>
#define pld pair <ld, ld>
#define all(a) a.begin(), a.end()
#define vvl vector <vector <ll> >

typedef int ll;

typedef long double ld;

using namespace std;

const ll maxn = 1e6;
const ll maxk = 12;

ll n, m, k, t;

// ll C[maxn];

vector <pll> V[maxn];

vector <ll> vers[maxk];

// ll to[maxn];

// ll cnt0 = 0;

set <ll> S[maxk][maxk];

vector <pll> CS[maxn];

map <pll, set <pll> > F;

set <pll> bad;

set <pll> very_bad;

map <pll, ll> C;

// vector <ll> I;

ll find_ans(ll i) {
    // if (i == k + 1) {
    //     // for (auto i : I) {
    //     //     cout << i << " ";
    //     // }
    //     // cout << endl;
    //     return 1;
    // }
    ll ans = 0;
    // cout << i << " I" << endl;
    ll q;
    for (q = 0; q < i; q++) {
        pll p1 = {i, q};
        // cout
        // cout << F[p1].size() << endl;
        if (bad.find(p1) != bad.end()) {
            continue;
        }
        if (i == k) {
            if (very_bad.find(p1) == very_bad.end()) {
                ans++;
            }
            continue;
        }
        for (auto p : F[p1]) {
            C[p]++;
            if (C[p] == 1) {
                bad.insert(p);
            }
        }
        if (bad.find(p1) == bad.end()) {
            // I.pb(q);
            ans += find_ans(i + 1);
            // I.pop_back();
            // continue;
        }
        for (auto p : F[p1]) {
            C[p]--;
            if (C[p] == 0) {
                bad.erase(p);
            }
        }
    }
    return ans;
}

int main() {
    pyshnapyshnakaa;
    ll q, w, e, a, b, c;
    cin >> n >> m >> k;
    for (q = 0; q < m; q++) {
        cin >> a >> b >> c;
        a--; b--;
        V[a].pb(mp(c, b));
    }
    for (q = 0; q < n; q++) {
        sort(all(V[q]));
    }
    for (q = 0; q < n; q++) {
        // to[q] = -1;
        vers[V[q].size()].pb(q);
    }
    // cnt0 = n;
    for (q = 1; q <= k; q++) {
        for (w = 0; w < q; w++) {
        // cout << "Q " <<  q << " " << vers[q].size() << endl;
            for (auto v : vers[q]) {
                // cout << q << " " << w << endl;
    // cout << "FALL" << endl;
                // cout << q << " " << w << " " << v << " " << V[v].size() << endl;
                // S[q][w].insert(V[v][w].second);
                CS[V[v][w].second].pb(mp(q, w));
            }
        }
    }
    // for (auto v : S[1][0]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[2][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[3][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[4][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    for (q = 0; q < n; q++) {
        for (int i = 0; i < CS[q].size(); i++) {
            for (int j = i + 1; j < CS[q].size(); j++) {
                pll p1 = CS[q][i], p2 = CS[q][j];
                if (p1 == p2) {
                    very_bad.insert(p1);
                }
                if (p1.first <= p2.first) {
                    F[p1].insert(p2);
                }
                else {
                    F[p2].insert(p1);
                }
                // cout << p1.first << " " << p1.second << " P " << p2.first << " " << p2.second << endl;
            }
        }
    }
    ll ans = find_ans(1);
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define pll pair <ll, ll>
#define mp make_pair
#define pyshnapyshnakaa ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define x first
#define y second
#pragma GCC optimize("O3")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
#define plll pair <pair <ll, ll>, ll>
#define pllll pair <pair <ll, ll>, pair <ll, ll> >
#define psl pair <string, ll>
#define pld pair <ld, ld>
#define all(a) a.begin(), a.end()
#define vvl vector <vector <ll> >

typedef int ll;

typedef long double ld;

using namespace std;

const ll maxn = 1e6;
const ll maxk = 12;

ll n, m, k, t;

// ll C[maxn];

vector <pll> V[maxn];

vector <ll> vers[maxk];

// ll to[maxn];

// ll cnt0 = 0;

set <ll> S[maxk][maxk];

vector <pll> CS[maxn];

map <pll, vector <pll>> F;

set <pll> bad;

set <pll> very_bad;

map <pll, ll> C;

// vector <ll> I;

ll find_ans(ll i) {
    // if (i == k + 1) {
    //     // for (auto i : I) {
    //     //     cout << i << " ";
    //     // }
    //     // cout << endl;
    //     return 1;
    // }
    ll ans = 0;
    // cout << i << " I" << endl;
    ll q;
    for (q = 0; q < i; q++) {
        pll p1 = {i, q};
        // cout
        // cout << F[p1].size() << endl;
        if (bad.find(p1) != bad.end()) {
            continue;
        }
        if (i == k) {
            if (very_bad.find(p1) == very_bad.end()) {
                ans++;
            }
            continue;
        }
        for (auto p : F[p1]) {
            C[p]++;
            if (C[p] == 1) {
                bad.insert(p);
            }
        }
        if (bad.find(p1) == bad.end()) {
            // I.pb(q);
            ans += find_ans(i + 1);
            // I.pop_back();
            // continue;
        }
        for (auto p : F[p1]) {
            C[p]--;
            if (C[p] == 0) {
                bad.erase(p);
            }
        }
    }
    return ans;
}

int main() {
    pyshnapyshnakaa;
    ll q, w, e, a, b, c;
    cin >> n >> m >> k;
    for (q = 0; q < m; q++) {
        cin >> a >> b >> c;
        a--; b--;
        V[a].pb(mp(c, b));
    }
    for (q = 0; q < n; q++) {
        sort(all(V[q]));
    }
    for (q = 0; q < n; q++) {
        // to[q] = -1;
        vers[V[q].size()].pb(q);
    }
    // cnt0 = n;
    for (q = 1; q <= k; q++) {
        for (w = 0; w < q; w++) {
        // cout << "Q " <<  q << " " << vers[q].size() << endl;
            for (auto v : vers[q]) {
                // cout << q << " " << w << endl;
    // cout << "FALL" << endl;
                // cout << q << " " << w << " " << v << " " << V[v].size() << endl;
                // S[q][w].insert(V[v][w].second);
                CS[V[v][w].second].pb(mp(q, w));
            }
        }
    }
    // for (auto v : S[1][0]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[2][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[3][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[4][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    for (q = 0; q < n; q++) {
        for (int i = 0; i < CS[q].size(); i++) {
            for (int j = i + 1; j < CS[q].size(); j++) {
                pll p1 = CS[q][i], p2 = CS[q][j];
                if (p1 == p2) {
                    very_bad.insert(p1);
                }
                if (p1.first <= p2.first) {
                    F[p1].pb(p2);
                }
                else {
                    F[p2].pb(p1);
                }
                // cout << p1.first << " " << p1.second << " P " << p2.first << " " << p2.second << endl;
            }
        }
    }
    ll ans = find_ans(1);
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define pll pair <ll, ll>
#define mp make_pair
#define pyshnapyshnakaa ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define x first
#define y second
#pragma GCC optimize("O3")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
#define plll pair <pair <ll, ll>, ll>
#define pllll pair <pair <ll, ll>, pair <ll, ll> >
#define psl pair <string, ll>
#define pld pair <ld, ld>
#define all(a) a.begin(), a.end()
#define vvl vector <vector <ll> >

typedef long long ll;

typedef long double ld;

using namespace std;

const ll maxn = 1e6;
const ll maxk = 12;

ll n, m, k, t;

// ll C[maxn];

vector <pll> V[maxn];

vector <ll> vers[maxk];

// ll to[maxn];

// ll cnt0 = 0;

set <ll> S[maxk][maxk];

vector <pll> CS[maxn];

map <pll, vector <pll>> F;

set <pll> bad;

map <pll, ll> C;

// vector <ll> I;

ll find_ans(ll i) {
    if (i == k + 1) {
        // for (auto i : I) {
        //     cout << i << " ";
        // }
        // cout << endl;
        return 1;
    }
    ll ans = 0;
    // cout << i << " I" << endl;
    ll q;
    for (q = 0; q < i; q++) {
        pll p1 = {i, q};
        // cout
        // cout << F[p1].size() << endl;
        if (bad.find(p1) != bad.end()) {
            continue;
        }
        if (i == k) {
            ans++;
            continue;
        }
        for (auto p : F[p1]) {
            C[p]++;
            if (C[p] == 1) {
                bad.insert(p);
            }
        }
        if (bad.find(p1) == bad.end()) {
            // I.pb(q);
            ans += find_ans(i + 1);
            // I.pop_back();
            // continue;
        }
        for (auto p : F[p1]) {
            C[p]--;
            if (C[p] == 0) {
                bad.erase(p);
            }
        }
    }
    return ans;
}

int main() {
    pyshnapyshnakaa;
    ll q, w, e, a, b, c;
    cin >> n >> m >> k;
    for (q = 0; q < m; q++) {
        cin >> a >> b >> c;
        a--; b--;
        V[a].pb(mp(c, b));
    }
    for (q = 0; q < n; q++) {
        sort(all(V[q]));
    }
    for (q = 0; q < n; q++) {
        // to[q] = -1;
        vers[V[q].size()].pb(q);
    }
    // cnt0 = n;
    for (q = 1; q <= k; q++) {
        for (w = 0; w < q; w++) {
        // cout << "Q " <<  q << " " << vers[q].size() << endl;
            for (auto v : vers[q]) {
                // cout << q << " " << w << endl;
    // cout << "FALL" << endl;
                // cout << q << " " << w << " " << v << " " << V[v].size() << endl;
                // S[q][w].insert(V[v][w].second);
                CS[V[v][w].second].pb(mp(q, w));
            }
        }
    }
    // for (auto v : S[1][0]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[2][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[3][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    // for (auto v : S[4][1]) {
    //     cout << v << " ";
    // }
    // cout << endl;
    for (q = 0; q < n; q++) {
        for (int i = 0; i < CS[q].size(); i++) {
            for (int j = i + 1; j < CS[q].size(); j++) {
                pll p1 = CS[q][i], p2 = CS[q][j];
                if (p1.first <= p2.first) {
                    F[p1].pb(p2);
                }
                else {
                    F[p2].pb(p1);
                }
                // cout << p1.first << " " << p1.second << " P " << p2.first << " " << p2.second << endl;
            }
        }
    }
    ll ans = find_ans(1);
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define ar array

const int P=37, MOD=1e9+9;
int n, m, k, val[200000]; //hash val for each number 1-n
vector<pair<int, int>> adj[200000];
int out[10][10]; //hash values
ll need=0;

int ans=0;
void rec(int x=1, int sum=0) {
	if (x==k+1) {
		if (sum==need) ++ans;
		return;
	}
	for (int i=0; i<x; ++i)
		rec(x+1, sum+out[x][i]);
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m >> k;
	for (int i=0; i<m; ++i) {
		int a, b, w; cin >> a >> b >> w, --a, --b;
		adj[a].emplace_back(w, b);
	}
	ll pp=1;
	for (int i=0; i<n; ++i) {
		val[i]=(i+1)*pp%MOD;
		need=(need+val[i])%MOD;
		pp=pp*P%MOD;
	}
	for (int i=0; i<n; ++i) {
		sort(adj[i].begin(), adj[i].end());
		for (int j=0; j<adj[i].size(); ++j)
			out[adj[i].size()][j]=(out[adj[i].size()][j]+val[adj[i][j].second])%MOD;
	}
	rec();
	cout << ans;
	return 0;
}

/* stuff you should look for
	* int overflow, array bounds
	* special cases (n=1?)
	* do smth instead of nothing and stay organized
	* WRITE STUFF DOWN
*/