#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
vector<pair<int, int>> G[N];
set<pair<int, int>> in_edges[N];
set<pair<int, int>> forbidden_pos;
set<pair<pair<int, int>, pair<int, int>>> forbidden_pairs;
int count(vector<int>& C, int k);
int main() {
  int n, m, k;
  scanf("%d%d%d", &n, &m, &k);
  while (m--) {
    int u, v, w;
    scanf("%d%d%d", &u, &v, &w);
    G[u].emplace_back(w, v);
  }
  for (int i = 1; i <= n; i++) sort(G[i].begin(), G[i].end());
  for (int i = 1; i <= n; i++) {
    for (int j = 0; j < int(G[i].size()); j++) {
      if (in_edges[G[i][j].second].count({G[i].size(), j + 1}) != 0)
        forbidden_pos.insert({G[i].size(), j + 1});
      in_edges[G[i][j].second].insert({G[i].size(), j + 1});
    }
  }
  for (int i = 1; i <= n; i++) {
    vector<pair<int, int>> V(in_edges[i].begin(), in_edges[i].end());
    for (auto a : V) {
      for (auto b : V) {
        forbidden_pairs.insert({a, b});
      }
    }
  }
  vector<int> C;
  printf("%d\n", count(C, k));
}
int count(vector<int>& C, int k) {
  if (int(C.size()) == k) {
    return 1;
  }
  int res = 0;
  for (int i = 1; i <= int(C.size() + 1); i++) {
    if (forbidden_pos.count({C.size() + 1, i}) != 0) continue;
    bool conflict = false;
    for (int j = 0; j < int(C.size()); j++) {
      if (forbidden_pairs.count({{j + 1, C[j]}, {C.size() + 1, i}}) != 0) {
        conflict = true;
        break;
      }
    }
    if (!conflict) {
      C.push_back(i);
      res += count(C, k);
      C.pop_back();
    }
  }
  return res;
}
