#include "bits/stdc++.h"
#include <queue>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
#define endl '\n'
#define debug(x) cerr << #x << " == " << (x) << '\n';
#define all(X) X.begin(), X.end()
#define sz(X) (int)X.size()

using ll = long long;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fLL;

// xz

const int MAX = 2000 * 2000, V = 5;
int E[MAX][V];
int sz[MAX];

int main()
{ _
    memset(E, -1, sizeof(E));
    memset(sz, 0, sizeof(sz));

    int n, m; cin >> n >> m;

    const int N = n * m;

    auto id = [&](int i, int j) { return m * i + j; };
    auto valid = [&](int i, int j) { return 0 <= i && i < n && 0 <= j && j < m; };

    vector a(N, 0);

    for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j)
        {
            char c; cin >> c;
            a[id(i, j)] = c - 'a';
        }

    int dx[4] = {1, 0, -1, 0};
    int dy[4] = {0, 1, 0, -1};

    queue<int> q;
    vector dist(N, INF);

    for (int x = 0; x < N; ++x)
        for (int k = 0; k < 4; ++k)
        {
            pair p = {x / m + dx[k], x % m + dy[k]};
            int y = id(p.first, p.second);
            if (valid(p.first, p.second)) E[x][sz[x]++] = y;
            if (not valid(p.first, p.second) || a[x] != a[y])
            {
                dist[x] = 0;
                q.push(x);
            }
        }

    auto chmin = [](int& x, int y) { return x > y ? 1, x = y : 0; };

    while (not q.empty())
    {
        int u = q.front(); q.pop();
        for (auto v : E[u])
        {
            if (v == -1) break;
            if (a[u] == a[v] && chmin(dist[v], dist[u] + 1))
                q.push(v);
        }
    }

    int ans = 0;
    for (int u = 0; u < N; ++u)
        ans += dist[u] + 1;

    cout << ans << endl;

    exit(0);
}


#include<bits/stdc++.h>
using namespace std;
using pii = pair<int,int>;
const int N = 2e5+10;
vector<pii> G[N];
int n,m,k,i,j,l;
long long hashed[11][11];
long long cor_hash;
long long ran[N];
int ans;

void genCheck(int a[], int pl)
{
    if(pl == k+1)
    {
        bool pass = true;
        int i,j;
        long long here = 0;
        for(i=0;i<k;i++)
        {
            here+=hashed[i+1][a[i]];
        }
        if(here == cor_hash)
        {
            ans++;
        }
    }
    else
    {
        int t;
        for(t=1;t<=pl;t++)
        {
            a[pl-1] = t;
            genCheck(a,pl+1);
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    long long seed = 7;
    for(i=0;i<N;i++)
    {
        ran[i] = seed;
        seed*=1543;
        seed+=29;
    }
    cin>>n>>m>>k;
    for(i=0;i<n;i++)
        cor_hash+=ran[i];
    for(i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        a--,b--;
        G[a].push_back({c,b});
    }
    for(i=0;i<n;i++)
        sort(G[i].begin(),G[i].end());
    for(i=0;i<n;i++)
    {
        for(j=0;j<G[i].size();j++)
        {
            pii cur = G[i][j];
            hashed[G[i].size()][j+1]+=ran[cur.second];
        }
    }
    int a[n];
    genCheck(a,1);
    cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;
using pii = pair<int,int>;
const int N = 2e5+10;
vector<pii> G[N];
int n,m,k,i,j,l;
long long hashed[11][11];
long long cor_hash;
long long ran[N];
int ans;

void genCheck(int a[], int pl)
{
    if(pl == k+1)
    {
        bool pass = true;
        int i,j;
        long long here = 0;
        for(i=0;i<k;i++)
        {
            here+=hashed[i+1][a[i]];
        }
        if(here == cor_hash)
        {
            ans++;
        }
    }
    else
    {
        int t;
        for(t=1;t<=pl;t++)
        {
            a[pl-1] = t;
            genCheck(a,pl+1);
        }
    }
}

int main()
{
    for(i=0;i<N;i++)
        ran[i] = rand();
    cin>>n>>m>>k;
    for(i=0;i<n;i++)
        cor_hash+=ran[i];
    for(i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        a--,b--;
        G[a].push_back({c,b});
    }
    for(i=0;i<n;i++)
        sort(G[i].begin(),G[i].end());
    for(i=0;i<n;i++)
    {
        for(j=0;j<G[i].size();j++)
        {
            pii cur = G[i][j];
            hashed[G[i].size()][j+1]+=ran[cur.second];
        }
    }
    int a[n];
    genCheck(a,1);
    cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;
using pii = pair<int,int>;
const int N = 2e5+10;
vector<pii> G[N];
vector<pii> re_G[N];
set<pii> forbid;
int n,m,k,i,j,l;
int ans;

void genCheck(int a[], int pl)
{
    if(pl == k+1)
    {
        bool pass = true;
        int i,j;
        for(i=0;i<k;i++)
        {
            for(j=0;j<=i;j++)
            {
                int val1 = 10*i+a[i]+10;
                int val2 = 10*j+a[j]+10;
                if(forbid.count({val2,val1}))
                    pass = false;
            }
        }
        if(pass)
            ans++;
    }
    else
    {
        int t;
        for(t=1;t<=pl;t++)
        {
            a[pl-1] = t;
            genCheck(a,pl+1);
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin>>n>>m>>k;
    for(i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        a--,b--;
        G[a].push_back({c,b});
    }
    for(i=0;i<n;i++)
        sort(G[i].begin(),G[i].end());
    for(i=0;i<n;i++)
    {
        for(j=0;j<G[i].size();j++)
        {
            pii cur = G[i][j];
            int node = G[i][j].second;
            re_G[node].push_back({j+1,i});
        }
    }
    for(i=0;i<n;i++)
    {
        for(j=0;j<re_G[i].size();j++)
        {
            for(l=0;l<j;l++)
            {
                pii fi = re_G[i][l];
                pii se = re_G[i][j];
                int val1 = 10*G[re_G[i][l].second].size() + re_G[i][l].first;
                int val2 = 10*G[re_G[i][j].second].size() + re_G[i][j].first;
                if(val1 > val2)
                    swap(val1,val2);
                if(!forbid.count({val1,val2}))
                    forbid.insert({val1,val2});
            }
        }
    }
    int a[n];
    genCheck(a,1);
    cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;
using pii = pair<int,int>;
const int N = 2e5+10;
vector<pii> G[N];
vector<pii> re_G[N];
set<pii> forbid;
int n,m,k,i,j,l;
int ans;

void genCheck(int a[], int pl)
{
    if(pl == k+1)
    {
        bool pass = true;
        int i,j;
        for(i=0;i<k;i++)
        {
            for(j=0;j<=i;j++)
            {
                int val1 = 10*i+a[i]+10;
                int val2 = 10*j+a[j]+10;
                if(forbid.count({val2,val1}))
                    pass = false;
            }
        }
        if(pass)
            ans++;
    }
    else
    {
        int t;
        for(t=1;t<=pl;t++)
        {
            a[pl-1] = t;
            genCheck(a,pl+1);
        }
    }
}

int main()
{
    cin>>n>>m>>k;
    for(i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        a--,b--;
        G[a].push_back({c,b});
    }
    for(i=0;i<n;i++)
        sort(G[i].begin(),G[i].end());
    for(i=0;i<n;i++)
    {
        for(j=0;j<G[i].size();j++)
        {
            pii cur = G[i][j];
            int node = G[i][j].second;
            re_G[node].push_back({j+1,i});
        }
    }
    for(i=0;i<n;i++)
    {
        for(j=0;j<re_G[i].size();j++)
        {
            for(l=0;l<j;l++)
            {
                pii fi = re_G[i][l];
                pii se = re_G[i][j];
                int val1 = 10*G[re_G[i][l].second].size() + re_G[i][l].first;
                int val2 = 10*G[re_G[i][j].second].size() + re_G[i][j].first;
                if(val1 > val2)
                    swap(val1,val2);
                if(!forbid.count({val1,val2}))
                    forbid.insert({val1,val2});
            }
        }
    }
    int a[n];
    genCheck(a,1);
    cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;
using pii = pair<int,int>;
const int N = 2e5+10;
vector<pii> G[N];
int n,m,k,i,j,l;
long long hashed[11][11];
long long cor_hash;
long long ran[N];
int ans;

void genCheck(int a[], int pl)
{
    if(pl == k+1)
    {
        bool pass = true;
        int i,j;
        long long here = 0;
        for(i=0;i<k;i++)
        {
            here+=hashed[i+1][a[i]];
        }
        if(here == cor_hash)
        {
            ans++;
        }
    }
    else
    {
        int t;
        for(t=1;t<=pl;t++)
        {
            a[pl-1] = t;
            genCheck(a,pl+1);
        }
    }
}

int main()
{
    long long seed = 7;
    for(i=0;i<N;i++)
    {
        ran[i] = seed;
        seed*=1543;
        seed+=29;
    }
    cin>>n>>m>>k;
    for(i=0;i<n;i++)
        cor_hash+=ran[i];
    for(i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        a--,b--;
        G[a].push_back({c,b});
    }
    for(i=0;i<n;i++)
        sort(G[i].begin(),G[i].end());
    for(i=0;i<n;i++)
    {
        for(j=0;j<G[i].size();j++)
        {
            pii cur = G[i][j];
            hashed[G[i].size()][j+1]+=ran[cur.second];
        }
    }
    int a[n];
    genCheck(a,1);
    cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;
using pii = pair<int,int>;
const int N = 2e5+10;
vector<pii> G[N];
vector<pii> re_G[N];
set<pii> forbid;
int n,m,k,i,j,l;
int ans;

void genCheck(int a[], int pl)
{
    if(pl == k+1)
    {
        bool pass = true;
        int i,j;
        for(i=0;i<k;i++)
        {
            for(j=0;j<=i;j++)
            {
                int val1 = 10*i+a[i]+10;
                int val2 = 10*j+a[j]+10;
                if(forbid.count({val2,val1}))
                    pass = false;
            }
        }
        if(pass)
            ans++;
    }
    else
    {
        int t;
        for(t=1;t<=pl;t++)
        {
            a[pl-1] = t;
            genCheck(a,pl+1);
        }
    }
}

int main()
{
    cin>>n>>m>>k;
    for(i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        a--,b--;
        G[a].push_back({c,b});
    }
    for(i=0;i<n;i++)
        sort(G[i].begin(),G[i].end());
    for(i=0;i<n;i++)
    {
        for(j=0;j<G[i].size();j++)
        {
            pii cur = G[i][j];
            int node = G[i][j].second;
            re_G[node].push_back({j+1,i});
        }
    }
    for(i=0;i<n;i++)
    {
        for(j=0;j<re_G[i].size();j++)
        {
            for(l=0;l<j;l++)
            {
                pii fi = re_G[i][l];
                pii se = re_G[i][j];
                int val1 = 10*G[re_G[i][l].second].size() + re_G[i][l].first;
                int val2 = 10*G[re_G[i][j].second].size() + re_G[i][j].first;
                if(val1 > val2)
                    swap(val1,val2);
                forbid.insert({val1,val2});
            }
        }
    }
    int a[n];
    genCheck(a,1);
    cout<<ans;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double LD;
using namespace std;
const int INF = 2147483647;
const int INF2 = 0x3f3f3f3f;
const ll INF64 = 4e18;
const double INFD = 1e30;
const double EPS = 1e-10;
const long double PI = acosl(-1);
const int MOD = 1e9 + 7;
template <typename T>
inline T read() {
    T X = 0, w = 0;
    char ch = 0;
    while (!isdigit(ch)) {
        w |= ch == '-';
        ch = getchar();
    }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
const int MAXN = 200005;
const int MAXV = 60;
int n, m, k;
int dr[4] = {1, 0, -1, 0};
int dc[4] = {0, 1, 0, -1};
int dr2[8] = {1, 1, 1, -1, -1, -1, 0, 0};
int dc2[8] = {1, 0, -1, 1, 0, -1, 1, -1};
int CASE = 1;
struct Edge {
    int to, w;
    bool operator<(const Edge& e) const { return w < e.w; }
};
int hash1[60], hash2[60];
vector<Edge> G[MAXN];
vector<int> C[10];
int ans;
int H1, H2;
void dfs(int x) {
    if (x == k + 1) {
        if (H1 == (ll)n * (n + 1) / 2 &&
            H2 == (ll)n * (n + 1) * (2 * n + 1) / 6) {
            ans++;
        }
        return;
    }
    for (int i = 1; i <= x; i++) {
        int id = (x - 1) * x / 2 + i;
        int pH1 = H1, pH2 = H2;
        H1 = H1 + hash1[id];
        H2 = H2 + hash2[id];
        dfs(x + 1);
        H1 = pH1;
        H2 = pH2;
    }
}

void solve() {
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        G[u].push_back({v, w});
    }
    for (int i = 1; i <= n; i++) {
        sort(G[i].begin(), G[i].end());
        C[G[i].size()].push_back(i);
    }
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= i; j++) {
            int id = (i - 1) * i / 2 + j;
            for (auto u : C[i]) {
                ll v = G[u][j - 1].to;
                hash1[id] += v;
                hash2[id] += v * v;
            }
        }
    }
    H1 = 0, H2 = 0;
    dfs(1);
    printf("%d", ans);
}
int main() {
#ifdef LOCALLL
    freopen("in", "r", stdin);
    freopen("out", "w", stdout);
#endif
    solve();
    return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double LD;
using namespace std;
const int INF = 2147483647;
const int INF2 = 0x3f3f3f3f;
const ll INF64 = 4e18;
const double INFD = 1e30;
const double EPS = 1e-10;
const long double PI = acosl(-1);
const int MOD = 1e9 + 7;
template <typename T>
inline T read() {
    T X = 0, w = 0;
    char ch = 0;
    while (!isdigit(ch)) {
        w |= ch == '-';
        ch = getchar();
    }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
const int MAXN = 200005;
const int MAXV = 60;
int n, m, k;
int dr[4] = {1, 0, -1, 0};
int dc[4] = {0, 1, 0, -1};
int dr2[8] = {1, 1, 1, -1, -1, -1, 0, 0};
int dc2[8] = {1, 0, -1, 1, 0, -1, 1, -1};
int CASE = 1;
struct Edge {
    int to, w;
    bool operator<(const Edge& e) const { return w < e.w; }
};
vector<Edge> G[MAXN];
int C[10];
int dfn[MAXN];
int low[MAXN];
bool vis[MAXN];
int sz[MAXN];
int scc[MAXN];
int timed;
stack<int> st;
int cnt;
int need[10];
bool can;
void tarjan(int u) {
    if (!can) return;
    dfn[u] = low[u] = ++timed;
    st.push(u);
    vis[u] = true;
    for (auto v : G[u]) {
        if (!dfn[v.to]) {
            tarjan(v.to);
            low[u] = min(low[u], low[v.to]);
        } else if (vis[v.to]) {
            low[u] = min(low[u], dfn[v.to]);
        }
    }
    // 如果u是强连通分量的根
    if (dfn[u] == low[u]) {
        if (u != 1 || st.size() != n) {
            can = false;
            return;
        }
        vector<int> ss;
        while (!st.empty()) {
            int p = st.top();
            st.pop();
            ss.push_back(p);
        }
        reverse(ss.begin(), ss.end());
        for (int i = 0; i < n; i++) {
            int rk = 1;
            bool found = false;
            for (auto e : G[ss[i]]) {
                if (e.to == ss[(i + 1) % n]) {
                    found = true;
                    if (need[G[ss[i]].size()] == 0 ||
                        need[G[ss[i]].size()] == rk) {
                        need[G[ss[i]].size()] = rk;
                    } else {
                        can = false;
                        break;
                    }
                }
                rk++;
            }
            if (!found) can = false;
        }
    }
}

void solve() {
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        G[u].push_back({v, w});
    }

    for (int i = 1; i <= n; i++) {
        sort(G[i].begin(), G[i].end());
        C[G[i].size()]++;
    }
    can = true;
    tarjan(1);
    if (!can) {
        printf("0");
        return;
    }
    ll ans = 1;
    for (int i = 1; i <= k; i++) {
        if (!C[i]) {
            ans *= i;
        }
    }
    printf("%lld\n", ans);
}
int main() {
#ifdef LOCALLL
    freopen("in", "r", stdin);
    freopen("out", "w", stdout);
#endif
    solve();
    return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double LD;
using namespace std;
const int INF = 2147483647;
const int INF2 = 0x3f3f3f3f;
const ll INF64 = 4e18;
const double INFD = 1e30;
const double EPS = 1e-10;
const long double PI = acosl(-1);
const int MOD = 1e9 + 7;
template <typename T>
inline T read() {
    T X = 0, w = 0;
    char ch = 0;
    while (!isdigit(ch)) {
        w |= ch == '-';
        ch = getchar();
    }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
const int MAXN = 200005;
const int MAXV = 60;
int n, m, k;
int dr[4] = {1, 0, -1, 0};
int dc[4] = {0, 1, 0, -1};
int dr2[8] = {1, 1, 1, -1, -1, -1, 0, 0};
int dc2[8] = {1, 0, -1, 1, 0, -1, 1, -1};
int CASE = 1;
struct Edge {
    int to, w;
    bool operator<(const Edge& e) const { return w < e.w; }
};
vector<Edge> G[MAXN];
int C[10];
int dfn[MAXN];
int low[MAXN];
bool vis[MAXN];
int sz[MAXN];
int scc[MAXN];
int timed;
stack<int> st;
int cnt;
int need[10];
bool can;
void tarjan(int u) {
    if (!can) return;
    dfn[u] = low[u] = ++timed;
    st.push(u);
    vis[u] = true;
    for (auto v : G[u]) {
        if (!dfn[v.to]) {
            tarjan(v.to);
            low[u] = min(low[u], low[v.to]);
        } else if (vis[v.to]) {
            low[u] = min(low[u], dfn[v.to]);
        }
    }
    // 如果u是强连通分量的根
    if (dfn[u] == low[u]) {
        if (u != 1 || st.size() != n) {
            can = false;
            return;
        }
        vector<int> ss;
        while (!st.empty()) {
            int p = st.top();
            st.pop();
            ss.push_back(p);
        }
        reverse(ss.begin(), ss.end());
        for (int i = 0; i < n; i++) {
            int rk = 1;
            for (auto e : G[ss[i]]) {
                if (e.to == ss[(i + 1) % n]) {
                    if (need[G[ss[i]].size()] == 0 ||
                        need[G[ss[i]].size()] == rk) {
                        need[G[ss[i]].size()] = rk;
                    } else {
                        can = false;
                        break;
                    }
                }
                rk++;
            }
        }
    }
}

void solve() {
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        G[u].push_back({v, w});
    }

    for (int i = 1; i <= n; i++) {
        sort(G[i].begin(), G[i].end());
        C[G[i].size()]++;
    }
    can = true;
    tarjan(1);
    if (!can) {
        printf("0");
        return;
    }
    ll ans = 1;
    for (int i = 1; i <= k; i++) {
        if (!C[i]) {
            ans *= i;
        }
    }
    printf("%lld\n", ans);
}
int main() {
#ifdef LOCALLL
    freopen("in", "r", stdin);
    freopen("out", "w", stdout);
#endif
    solve();
    return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double LD;
using namespace std;
const int INF = 2147483647;
const int INF2 = 0x3f3f3f3f;
const ll INF64 = 4e18;
const double INFD = 1e30;
const double EPS = 1e-10;
const long double PI = acosl(-1);
const int MOD = 1e9 + 7;
template <typename T>
inline T read() {
    T X = 0, w = 0;
    char ch = 0;
    while (!isdigit(ch)) {
        w |= ch == '-';
        ch = getchar();
    }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
const int MAXN = 200005;
const int MAXV = 60;
int n, m, k;
int dr[4] = {1, 0, -1, 0};
int dc[4] = {0, 1, 0, -1};
int dr2[8] = {1, 1, 1, -1, -1, -1, 0, 0};
int dc2[8] = {1, 0, -1, 1, 0, -1, 1, -1};
int CASE = 1;
struct Edge {
    int to, w;
    bool operator<(const Edge& e) const { return w < e.w; }
};
int hash1[60], hash2[60], hash3[60];
int pow2[MAXN];
vector<Edge> G[MAXN];
vector<int> C[10];
int ans;
int H1, H2, H3;
int h3target;
void dfs(int x) {
    if (x == k + 1) {
        if (H1 == (ll)n * (n + 1) / 2 &&
            H2 == (ll)n * (n + 1) * (2 * n + 1) / 6 && H3 == h3target) {
            ans++;
        }
        return;
    }
    for (int i = 1; i <= x; i++) {
        int id = (x - 1) * x / 2 + i;
        int pH1 = H1, pH2 = H2, pH3 = H3;
        H1 = H1 + hash1[id];
        H2 = H2 + hash2[id];
        H3 = (H3 + hash3[id]) % MOD;
        dfs(x + 1);
        H1 = pH1;
        H2 = pH2;
        H3 = pH3;
    }
}

void solve() {
    scanf("%d%d%d", &n, &m, &k);
    pow2[0] = 1;
    for (int i = 1; i <= n + 1; i++) {
        pow2[i] = (pow2[i - 1] << 1) % MOD;
    }
    h3target = (pow2[n + 1] - 2 + MOD) % MOD;
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        G[u].push_back({v, w});
    }
    for (int i = 1; i <= n; i++) {
        sort(G[i].begin(), G[i].end());
        C[G[i].size()].push_back(i);
    }
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= i; j++) {
            int id = (i - 1) * i / 2 + j;
            for (auto u : C[i]) {
                ll v = G[u][j - 1].to;
                hash1[id] += v;
                hash2[id] += v * v;
                hash3[id] += pow2[v];
                hash3[id] %= MOD;
            }
        }
    }
    H1 = 0, H2 = 0;
    dfs(1);
    printf("%d", ans);
}
int main() {
#ifdef LOCALLL
    freopen("in", "r", stdin);
    freopen("out", "w", stdout);
#endif
    solve();
    return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double LD;
using namespace std;
const int INF = 2147483647;
const int INF2 = 0x3f3f3f3f;
const ll INF64 = 4e18;
const double INFD = 1e30;
const double EPS = 1e-10;
const long double PI = acosl(-1);
const int MOD = 1e9 + 7;
template <typename T>
inline T read() {
    T X = 0, w = 0;
    char ch = 0;
    while (!isdigit(ch)) {
        w |= ch == '-';
        ch = getchar();
    }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
const int MAXN = 200005;
const int MAXV = 60;
int n, m, k;
int dr[4] = {1, 0, -1, 0};
int dc[4] = {0, 1, 0, -1};
int dr2[8] = {1, 1, 1, -1, -1, -1, 0, 0};
int dc2[8] = {1, 0, -1, 1, 0, -1, 1, -1};
int CASE = 1;
struct Edge {
    int to, w;
    bool operator<(const Edge& e) const { return w < e.w; }
};
vector<Edge> G[MAXN];
int C[10];
int dfn[MAXN];
int low[MAXN];
bool vis[MAXN];
int sz[MAXN];
int scc[MAXN];
int timed;
stack<int> st;
int cnt;
int need[10];
bool can;
void tarjan(int u) {
    if (!can) return;
    dfn[u] = low[u] = ++timed;
    st.push(u);
    vis[u] = true;
    for (auto v : G[u]) {
        if (!dfn[v.to]) {
            tarjan(v.to);
            low[u] = min(low[u], low[v.to]);
        } else if (vis[v.to]) {
            low[u] = min(low[u], dfn[v.to]);
        }
    }
    // 如果u是强连通分量的根
    if (dfn[u] == low[u]) {
        if (u != 1 || st.size() != n) {
            can = false;
            return;
        }
        vector<int> ss;
        while (!st.empty()) {
            int p = st.top();
            st.pop();
            ss.push_back(p);
        }
        reverse(ss.begin(), ss.end());
        for (int i = 0; i < n - 1; i++) {
            int rk = 1;
            for (auto e : G[ss[i]]) {
                if (e.to == ss[i + 1]) {
                    if (need[G[ss[i]].size()] == 0 ||
                        need[G[ss[i]].size()] == rk) {
                        need[G[ss[i]].size()] = rk;
                    } else {
                        can = false;
                        break;
                    }
                }
                rk++;
            }
        }
    }
}

void solve() {
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        G[u].push_back({v, w});
    }

    for (int i = 1; i <= n; i++) {
        sort(G[i].begin(), G[i].end());
        C[G[i].size()]++;
    }
    can = true;
    tarjan(1);
    if (!can) {
        printf("0");
        return;
    }
    ll ans = 1;
    for (int i = 1; i <= k; i++) {
        if (!C[i]) {
            ans *= i;
        }
    }
    printf("%lld\n", ans);
}
int main() {
#ifdef LOCALLL
    freopen("in", "r", stdin);
    freopen("out", "w", stdout);
#endif
    solve();
    return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double LD;
using namespace std;
const int INF = 2147483647;
const int INF2 = 0x3f3f3f3f;
const ll INF64 = 4e18;
const double INFD = 1e30;
const double EPS = 1e-10;
const long double PI = acosl(-1);
const int MOD = 1e9 + 7;
template <typename T>
inline T read() {
    T X = 0, w = 0;
    char ch = 0;
    while (!isdigit(ch)) {
        w |= ch == '-';
        ch = getchar();
    }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
const int MAXN = 200005;
const int MAXV = 60;
int n, m, k;
int dr[4] = {1, 0, -1, 0};
int dc[4] = {0, 1, 0, -1};
int dr2[8] = {1, 1, 1, -1, -1, -1, 0, 0};
int dc2[8] = {1, 0, -1, 1, 0, -1, 1, -1};
int CASE = 1;
struct Edge {
    int to, w;
    bool operator<(const Edge& e) const { return w < e.w; }
};
int hash1[60], hash2[60], hash3[60];
int pow2[MAXN];
vector<Edge> G[MAXN];
vector<int> C[10];
int ans;
int H1, H2, H3;
int h3target;
void dfs(int x) {
    if (x == k + 1) {
        if (H3 == h3target) {
            ans++;
        }
        return;
    }
    for (int i = 1; i <= x; i++) {
        int id = (x - 1) * x / 2 + i;
        int pH3 = H3;
        H3 = (H3 + hash3[id]) % MOD;
        dfs(x + 1);
        H3 = pH3;
    }
}

void solve() {
    scanf("%d%d%d", &n, &m, &k);
    pow2[0] = 1;
    for (int i = 1; i <= n + 1; i++) {
        pow2[i] = (pow2[i - 1] << 1) % MOD;
    }
    h3target = (pow2[n + 1] - 2 + MOD) % MOD;
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        G[u].push_back({v, w});
    }
    for (int i = 1; i <= n; i++) {
        sort(G[i].begin(), G[i].end());
        C[G[i].size()].push_back(i);
    }
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= i; j++) {
            int id = (i - 1) * i / 2 + j;
            for (auto u : C[i]) {
                ll v = G[u][j - 1].to;
                hash3[id] += pow2[v];
                hash3[id] %= MOD;
            }
        }
    }
    dfs(1);
    printf("%d", ans);
}
int main() {
#ifdef LOCALLL
    freopen("in", "r", stdin);
    freopen("out", "w", stdout);
#endif
    solve();
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define sample aavdsdvsdbss
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int maxn = 200000;
const int maxk = 9;
const int oo1 = (int) 1e9+7;
const int oo2 = (int) 1e9+9;
const int base = (int) 2e6;

int n, m, k;
vector<pii> g[maxn];
pii sample;
pii current;
pii delta[maxk+1][maxk];
pii add(pii a,pii b) { return { (a.X+b.X)%oo1, (a.Y+b.Y)%oo2 }; }
pii sub(pii a,pii b) { return { (a.X-b.X+oo1*oo1)%oo1, (a.Y-b.Y+oo2*oo2)%oo2}; }
pii multi(pii a,int b) { return { a.X*b%oo1, a.Y*b%oo2 }; }
bool cmp(pii a,pii b) { return a.Y < b.Y; }
int in_deg[maxn];
pii powB[maxn+1];
int x[maxk+1];
vi needed;
set<int> steps;
void init() {
	sample = {0,0};
	rep(i,0,n) sample = add(multi(sample, base), { 1, 1 });
	//cerr << sample.X << ' ' << sample.Y << endl;

	rep(i,0,n) in_deg[g[i][0].X]++;

	current = {0,0};
	for (int i=n-1; i>=0; i--)
		current = add(multi(current, base), { in_deg[i], in_deg[i] });

	powB[0] = {1,1};
	rep(i,1,n+1) powB[i] = multi(powB[i-1], base);

	rep(i,1,k+1) {
		needed.clear();
		rep(j,0,n) if (sz(g[j])==i) needed.pb(j);

		rep(j,0,i) {
			delta[i][j] = { 0, 0 };
			for (int z: needed) {
				//cerr << z << ' ';
				delta[i][j] = sub(delta[i][j], powB[g[z][(j-1+i)%i].X]); // in_deg old node decreases
				delta[i][j] = add(delta[i][j], powB[g[z][j].X]); // in_deg new node increases
			}
			//cerr << i << ' ' << j << ' ' << delta[i][j].X << ' ' << delta[i][j].Y << endl;
		}
	}
}

int res = 0;
void check() {
	//rep(i,1,k+1) cerr << x[i] << ' ';
	//cerr << current.X << ' ' << current.Y << ' ' << sample.X << ' ' << sample.Y << endl;
	if (current==sample) {
		steps.clear();
		int tmp = 0;
		int cnt = 0;
		steps.insert(0);
		do {
			//cerr << tmp << ' ';
			tmp = g[tmp][x[sz(g[tmp])]].X;
			//cerr << tmp << endl;
			if (steps.count(tmp)) break;
			steps.insert(tmp);
			cnt++;
		} while (cnt<n);
		//cerr << tmp << ' ' << cnt << ' ' << "I'm here\n";
		if (sz(steps)==n) res++;
	}
}

void quay(int i) {
	rep(j,0,i) {
		if (x[i]!=-1) { current=add(current, delta[i][j]); }
		x[i] = j;
		if (i<k) quay(i+1);
		else check();
	}
}

main() {
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(cin.failbit);
	cin >> n >> m >> k;
	rep(i,0,m) { int u,v,w; cin >> u >> v >> w; u--, v--; g[u].pb({v, w}); }
	rep(i,0,n) { if (sz(g[i])==0) { cout << 0; return 0; } }
	rep(i,0,n) { sort(all(g[i]),cmp); }
	init();
	rep(i,1,k+1) x[i] = -1;
	quay(1);
	cout << res;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int maxn = 200000;
const int maxk = 9;
const int oo1 = (int) 1e9+7;
const int oo2 = (int) 1e9+9;
const int base = (int) 2e6;

int n, m, k;
vector<pii> g[maxn];
pii sample;
pii current;
pii delta[maxk+1][maxk];
pii add(pii a,pii b) { return { (a.X+b.X)%oo1, (a.Y+b.Y)%oo2 }; }
pii sub(pii a,pii b) { return { (a.X-b.X+oo1*oo1)%oo1, (a.Y-b.Y+oo2*oo2)%oo2}; }
pii multi(pii a,int b) { return { a.X*b%oo1, a.Y*b%oo2 }; }
bool cmp(pii a,pii b) { return a.Y < b.Y; }
int in_deg[maxn];
pii powB[maxn+1];
int x[maxk+1];

void init() {
	sample = {0,0};
	rep(i,0,n) sample = add(multi(sample, base), { 1, 1 });
	cerr << sample.X << ' ' << sample.Y << endl;

	rep(i,0,n) in_deg[g[i][0].X]++;

	current = {0,0};
	for (int i=n-1; i>=0; i--)
		current = add(multi(current, base), { in_deg[i], in_deg[i] });

	powB[0] = {1,1};
	rep(i,1,n+1) powB[i] = multi(powB[i-1], base);

	rep(i,1,k+1) {
		vi needed; needed.clear();
		rep(j,0,n) if (sz(g[j])==i) needed.pb(j);
		rep(j,0,i) {
			delta[i][j] = { 0, 0 };
			for (int z: needed) {
				//cerr << z << ' ';
				delta[i][j] = sub(delta[i][j], powB[g[z][(j-1+k)%k].X]); // in_deg old node decreases
				delta[i][j] = add(delta[i][j], powB[g[z][j].X]); // in_deg new node increases
			}
			//cerr << i << ' ' << j << ' ' << delta[i][j].X << ' ' << delta[i][j].Y << endl;
		}
	}
}

int res = 0;
void check() {
	//rep(i,1,k+1) cerr << x[i] << ' ';
	//cerr << current.X << ' ' << current.Y << ' ' << sample.X << ' ' << sample.Y << endl;
	if (current==sample) {
		int tmp = 0;
		int cnt = 0;
		do {
			cerr << tmp << ' ';
			tmp = g[tmp][x[sz(g[tmp])]].X;
			cerr << tmp << endl;
			cnt++;
		} while (tmp!=0 and cnt<n);
		//cerr << tmp << ' ' << cnt << ' ' << "I'm here\n";
		if (tmp==0 and cnt==n) res++;
	}
}

void quay(int i) {
	rep(j,0,i) {
		if (x[i]!=-1) { current=add(current, delta[i][j]); }
		x[i] = j;
		if (i<k) quay(i+1);
		else check();
	}
}

main() {
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(cin.failbit);
	cin >> n >> m >> k;
	rep(i,0,m) { int u,v,w; cin >> u >> v >> w; u--, v--; g[u].pb({v, w}); }
	rep(i,0,n) { if (sz(g[i])==0) { cout << 0; return 0; } }
	rep(i,0,n) { sort(all(g[i]),cmp); }
	init();
	rep(i,1,k+1) x[i] = -1;
	quay(1);
	cout << res;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define sample aavdsdvsdbss
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int maxn = 200000;
const int maxk = 9;
const int oo1 = (int) 1e9+7;
const int oo2 = (int) 1e9+9;
const int base = (int) 2e6;

int n, m, k;
vector<pii> g[maxn];
pii sample;
pii current;
pii delta[maxk+1][maxk];
pii add(pii a,pii b) { return { (a.X+b.X)%oo1, (a.Y+b.Y)%oo2 }; }
pii sub(pii a,pii b) { return { (a.X-b.X+oo1*oo1)%oo1, (a.Y-b.Y+oo2*oo2)%oo2}; }
pii multi(pii a,int b) { return { a.X*b%oo1, a.Y*b%oo2 }; }
bool cmp(pii a,pii b) { return a.Y < b.Y; }
int in_deg[maxn];
pii powB[maxn+1];
int x[maxk+1];
vi needed;
void init() {
	sample = {0,0};
	rep(i,0,n) sample = add(multi(sample, base), { 1, 1 });
	//cerr << sample.X << ' ' << sample.Y << endl;

	rep(i,0,n) in_deg[g[i][0].X]++;

	current = {0,0};
	for (int i=n-1; i>=0; i--)
		current = add(multi(current, base), { in_deg[i], in_deg[i] });

	powB[0] = {1,1};
	rep(i,1,n+1) powB[i] = multi(powB[i-1], base);

	rep(i,1,k+1) {
		needed.clear();
		rep(j,0,n) if (sz(g[j])==i) needed.pb(j);

		rep(j,0,i) {
			delta[i][j] = { 0, 0 };
			for (int z: needed) {
				//cerr << z << ' ';
				delta[i][j] = sub(delta[i][j], powB[g[z][(j-1+i)%i].X]); // in_deg old node decreases
				delta[i][j] = add(delta[i][j], powB[g[z][j].X]); // in_deg new node increases
			}
			//cerr << i << ' ' << j << ' ' << delta[i][j].X << ' ' << delta[i][j].Y << endl;
		}
	}
}

int res = 0;
void check() {
	//rep(i,1,k+1) cerr << x[i] << ' ';
	//cerr << current.X << ' ' << current.Y << ' ' << sample.X << ' ' << sample.Y << endl;
	if (current==sample) {
		/*int tmp = 0;
		int cnt = 0;
		do {
			//cerr << tmp << ' ';
			tmp = g[tmp][x[sz(g[tmp])]].X;
			//cerr << tmp << endl;
			cnt++;
		} while (tmp!=0 and cnt<n);*/
		//cerr << tmp << ' ' << cnt << ' ' << "I'm here\n";
		/*if (tmp==0 and cnt==n) */res++;
	}
}

void quay(int i) {
	rep(j,0,i) {
		if (x[i]!=-1) { current=add(current, delta[i][j]); }
		x[i] = j;
		if (i<k) quay(i+1);
		else check();
	}
}

main() {
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(cin.failbit);
	cin >> n >> m >> k;
	rep(i,0,m) { int u,v,w; cin >> u >> v >> w; u--, v--; g[u].pb({v, w}); }
	rep(i,0,n) { if (sz(g[i])==0) { cout << 0; return 0; } }
	rep(i,0,n) { sort(all(g[i]),cmp); }
	init();
	rep(i,1,k+1) x[i] = -1;
	quay(1);
	cout << res;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int maxn = 200000;
const int maxk = 9;
const int oo1 = (int) 1e9+7;
const int oo2 = (int) 1e9+9;
const int base = (int) 2e6;

int n, m, k;
vector<pii> g[maxn];
pii sample;
pii current;
pii delta[maxk+1][maxk];
pii add(pii a,pii b) { return { (a.X+b.X)%oo1, (a.Y+b.Y)%oo2 }; }
pii sub(pii a,pii b) { return { (a.X-b.X+oo1*oo1)%oo1, (a.Y-b.Y+oo2*oo2)%oo2}; }
pii multi(pii a,int b) { return { a.X*b%oo1, a.Y*b%oo2 }; }
bool cmp(pii a,pii b) { return a.Y < b.Y; }
int in_deg[maxn];
pii powB[maxn+1];
int x[maxk+1];

void init() {
	sample = {0,0};
	rep(i,0,n) sample = add(multi(sample, base), { 1, 1 });
	//cerr << sample.X << ' ' << sample.Y << endl;

	rep(i,0,n) in_deg[g[i][0].X]++;

	current = {0,0};
	for (int i=n-1; i>=0; i--)
		current = add(multi(current, base), { in_deg[i], in_deg[i] });

	powB[0] = {1,1};
	rep(i,1,n+1) powB[i] = multi(powB[i-1], base);

	rep(i,1,k+1) {
		vi needed; needed.clear();
		rep(j,0,n) if (sz(g[j])==i) needed.pb(j);
		rep(j,0,i) {
			delta[i][j] = { 0, 0 };
			for (int z: needed) {
				//cerr << z << ' ';
				delta[i][j] = sub(delta[i][j], powB[g[z][(j-1+k)%k].X]); // in_deg old node decreases
				delta[i][j] = add(delta[i][j], powB[g[z][j].X]); // in_deg new node increases
			}
			//cerr << i << ' ' << j << ' ' << delta[i][j].X << ' ' << delta[i][j].Y << endl;
		}
	}
}

int res = 0;
void check() {
	//rep(i,1,k+1) cerr << x[i] << ' ';
	//cerr << current.X << ' ' << current.Y << ' ' << sample.X << ' ' << sample.Y << endl;
	if (current==sample) {
		int tmp = 0;
		int cnt = 0;
		do {
			cerr << tmp << ' ';
			tmp = g[tmp][x[sz(g[tmp])]].X;
			cerr << tmp << endl;
			cnt++;
		} while (tmp!=0 and cnt<n);
		//cerr << tmp << ' ' << cnt << ' ' << "I'm here\n";
		if (tmp==0 and cnt==n) res++;
	}
}

void quay(int i) {
	rep(j,0,i) {
		if (x[i]!=-1) { current=add(current, delta[i][j]); }
		x[i] = j;
		if (i<k) quay(i+1);
		else check();
	}
}

main() {
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(cin.failbit);
	cin >> n >> m >> k;
	rep(i,0,m) { int u,v,w; cin >> u >> v >> w; u--, v--; g[u].pb({v, w}); }
	rep(i,0,n) { if (sz(g[i])==0) { cout << 0; return 0; } }
	rep(i,0,n) { sort(all(g[i]),cmp); }
	init();
	rep(i,1,k+1) x[i] = -1;
	quay(1);
	cout << res;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define sample aavdsdvsdbss
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int maxn = 200000;
const int maxk = 9;
const int oo1 = (int) 1e9+7;
const int oo2 = (int) 1e9+9;
const int base = (int) 2e6;

int n, m, k;
vector<pii> g[maxn];
pii sample;
pii current;
pii delta[maxk+1][maxk];
pii add(pii a,pii b) { return { (a.X+b.X)%oo1, (a.Y+b.Y)%oo2 }; }
pii sub(pii a,pii b) { return { (a.X-b.X+oo1*oo1)%oo1, (a.Y-b.Y+oo2*oo2)%oo2}; }
pii multi(pii a,int b) { return { a.X*b%oo1, a.Y*b%oo2 }; }
bool cmp(pii a,pii b) { return a.Y < b.Y; }
int in_deg[maxn];
pii powB[maxn+1];
int x[maxk+1];

void init() {
	sample = {0,0};
	rep(i,0,n) sample = add(multi(sample, base), { 1, 1 });
	//cerr << sample.X << ' ' << sample.Y << endl;

	rep(i,0,n) in_deg[g[i][0].X]++;

	current = {0,0};
	for (int i=n-1; i>=0; i--)
		current = add(multi(current, base), { in_deg[i], in_deg[i] });

	powB[0] = {1,1};
	rep(i,1,n+1) powB[i] = multi(powB[i-1], base);

	rep(i,1,k+1) {
		vi needed; needed.clear();
		rep(j,0,n) if (sz(g[j])==i) needed.pb(j);
		rep(j,0,i) {
			delta[i][j] = { 0, 0 };
			for (int z: needed) {
				//cerr << z << ' ';
				delta[i][j] = sub(delta[i][j], powB[g[z][(j-1+k)%k].X]); // in_deg old node decreases
				delta[i][j] = add(delta[i][j], powB[g[z][j].X]); // in_deg new node increases
			}
			//cerr << i << ' ' << j << ' ' << delta[i][j].X << ' ' << delta[i][j].Y << endl;
		}
	}
}

int res = 0;
void check() {
	//rep(i,1,k+1) cerr << x[i] << ' ';
	//cerr << current.X << ' ' << current.Y << ' ' << sample.X << ' ' << sample.Y << endl;
	if (current==sample) {
		int tmp = 0;
		int cnt = 0;
		do {
			//cerr << tmp << ' ';
			tmp = g[tmp][x[sz(g[tmp])]].X;
			//cerr << tmp << endl;
			cnt++;
		} while (tmp!=0 and cnt<n);
		//cerr << tmp << ' ' << cnt << ' ' << "I'm here\n";
		if (tmp==0 and cnt==n) res++;
	}
}

void quay(int i) {
	rep(j,0,i) {
		if (x[i]!=-1) { current=add(current, delta[i][j]); }
		x[i] = j;
		if (i<k) quay(i+1);
		else check();
	}
}

main() {
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(cin.failbit);
	cin >> n >> m >> k;
	rep(i,0,m) { int u,v,w; cin >> u >> v >> w; u--, v--; g[u].pb({v, w}); }
	rep(i,0,n) { if (sz(g[i])==0) { cout << 0; return 0; } }
	rep(i,0,n) { sort(all(g[i]),cmp); }
	init();
	rep(i,1,k+1) x[i] = -1;
	quay(1);
	cout << res;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int maxn = 200000;
const int maxk = 9;
const int oo1 = (int) 1e9+7;
const int oo2 = (int) 1e9+9;
const int base = (int) 2e6;

int n, m, k;
vector<pii> g[maxn];
pii sample;
pii current;
pii delta[maxk+1][maxk];
pii add(pii a,pii b) { return { (a.X+b.X)%oo1, (a.Y+b.Y)%oo2 }; }
pii sub(pii a,pii b) { return { (a.X-b.X+oo1*oo1)%oo1, (a.Y-b.Y+oo2*oo2)%oo2}; }
pii multi(pii a,int b) { return { a.X*b%oo1, a.Y*b%oo2 }; }
bool cmp(pii a,pii b) { return a.Y < b.Y; }
int in_deg[maxn];
pii powB[maxn+1];
int x[maxk+1];

void init() {
	sample = {0,0};
	rep(i,0,n) sample = add(multi(sample, base), { 1, 1 });
	//cerr << sample.X << ' ' << sample.Y << endl;

	rep(i,0,n) in_deg[g[i][0].X]++;

	current = {0,0};
	for (int i=n-1; i>=0; i--)
		current = add(multi(current, base), { in_deg[i], in_deg[i] });

	powB[0] = {1,1};
	rep(i,1,n+1) powB[i] = multi(powB[i-1], base);

	rep(i,1,k+1) {
		vi needed; needed.clear();
		rep(j,0,n) if (sz(g[j])==i) needed.pb(j);
		rep(j,0,i) {
			delta[i][j] = { 0, 0 };
			for (int z: needed) {
				//cerr << z << ' ';
				delta[i][j] = sub(delta[i][j], powB[g[z][(j-1+k)%k].X]); // in_deg old node decreases
				delta[i][j] = add(delta[i][j], powB[g[z][j].X]); // in_deg new node increases
			}
			//cerr << i << ' ' << j << ' ' << delta[i][j].X << ' ' << delta[i][j].Y << endl;
		}
	}
}

int res = 0;
void check() {
	//rep(i,1,k+1) cerr << x[i] << ' ';
	//cerr << current.X << ' ' << current.Y << ' ' << sample.X << ' ' << sample.Y << endl;
	if (current==sample) {
		int tmp = 0;
		int cnt = 0;
		do {
			//cerr << tmp << ' ';
			tmp = g[tmp][x[sz(g[tmp])]].X;
			//cerr << tmp << endl;
			cnt++;
		} while (tmp!=0 and cnt<n);
		//cerr << tmp << ' ' << cnt << ' ' << "I'm here\n";
		if (tmp==0 and cnt==n) res++;
	}
}

void quay(int i) {
	rep(j,0,i) {
		if (x[i]!=-1) { current=add(current, delta[i][j]); }
		x[i] = j;
		if (i<k) quay(i+1);
		else check();
	}
}

main() {
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(cin.failbit);
	cin >> n >> m >> k;
	rep(i,0,m) { int u,v,w; cin >> u >> v >> w; u--, v--; g[u].pb({v, w}); }
	rep(i,0,n) { if (sz(g[i])==0) { cout << 0; return 0; } }
	rep(i,0,n) { sort(all(g[i]),cmp); }
	init();
	rep(i,1,k+1) x[i] = -1;
	quay(1);
	cout << res;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define sample aavdsdvsdbss
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int maxn = 200000;
const int maxk = 9;
const int oo1 = (int) 1e9+7;
const int oo2 = (int) 1e9+9;
const int base = (int) 2e6;

int n, m, k;
vector<pii> g[maxn];
pii sample;
pii current;
pii delta[maxk+1][maxk];
pii add(pii a,pii b) { return { (a.X+b.X)%oo1, (a.Y+b.Y)%oo2 }; }
pii sub(pii a,pii b) { return { (a.X-b.X+oo1*oo1)%oo1, (a.Y-b.Y+oo2*oo2)%oo2}; }
pii multi(pii a,int b) { return { a.X*b%oo1, a.Y*b%oo2 }; }
bool cmp(pii a,pii b) { return a.Y < b.Y; }
int in_deg[maxn];
pii powB[maxn+1];
int x[maxk+1];
vi needed;
void init() {
	sample = {0,0};
	rep(i,0,n) sample = add(multi(sample, base), { 1, 1 });
	//cerr << sample.X << ' ' << sample.Y << endl;

	rep(i,0,n) in_deg[g[i][0].X]++;

	current = {0,0};
	for (int i=n-1; i>=0; i--)
		current = add(multi(current, base), { in_deg[i], in_deg[i] });

	powB[0] = {1,1};
	rep(i,1,n+1) powB[i] = multi(powB[i-1], base);

	rep(i,1,k+1) {
		needed.clear();
		rep(j,0,n) if (sz(g[j])==i) needed.pb(j);

		rep(j,0,i) {
			delta[i][j] = { 0, 0 };
			for (int z: needed) {
				//cerr << z << ' ';
				delta[i][j] = sub(delta[i][j], powB[g[z][(j-1+i)%i].X]); // in_deg old node decreases
				delta[i][j] = add(delta[i][j], powB[g[z][j].X]); // in_deg new node increases
			}
			//cerr << i << ' ' << j << ' ' << delta[i][j].X << ' ' << delta[i][j].Y << endl;
		}
	}
}

int res = 0;
void check() {
	//rep(i,1,k+1) cerr << x[i] << ' ';
	//cerr << current.X << ' ' << current.Y << ' ' << sample.X << ' ' << sample.Y << endl;
	if (current==sample) {
		int tmp = 0;
		int cnt = 0;
		do {
			//cerr << tmp << ' ';
			tmp = g[tmp][x[sz(g[tmp])]].X;
			//cerr << tmp << endl;
			cnt++;
		} while (tmp!=0 and cnt<n);
		//cerr << tmp << ' ' << cnt << ' ' << "I'm here\n";
		if (tmp==0 and cnt==n) res++;
	}
}

void quay(int i) {
	rep(j,0,i) {
		if (x[i]!=-1) { current=add(current, delta[i][j]); }
		x[i] = j;
		if (i<k) quay(i+1);
		else check();
	}
}

main() {
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(cin.failbit);
	cin >> n >> m >> k;
	rep(i,0,m) { int u,v,w; cin >> u >> v >> w; u--, v--; g[u].pb({v, w}); }
	rep(i,0,n) { if (sz(g[i])==0) { cout << 0; return 0; } }
	rep(i,0,n) { sort(all(g[i]),cmp); }
	init();
	rep(i,1,k+1) x[i] = -1;
	quay(1);
	cout << res;
}


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    int to,weight;
};

vector<Node>field[maxn];
vector<int>sum[10];
vector<int>origin;
int n,m,k;
int ans=0;
int tot=0;
ll tot1,tot2;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(int deep,ll now1,ll now2)
{
    if(deep==k)
    {
        if(now1==tot1&&now2==tot2) ans++;
        return;
    }
    for(int i=0;i<origin[deep];i++)
    {
        ll temp1=now1,temp2=now2;
        for(int j=0;j<sum[origin[deep]].size();j++)
        {
            ll to=sum[origin[deep]][j];
            to=field[to][i].to;
            temp1+=to*to-1;
            temp2+=to*to*to-1;
        }
        dfs(deep+1,temp1,temp2);
    }
}

bool cmp1(int a,int b)
{
    return sum[a].size()>sum[b].size();
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        int u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(int i=1;i<=n;i++)
    {
        tot1+=(ll)i*i-1;
        tot2+=(ll)i*i*i-1;
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    for(int i=1;i<=k;i++) origin.pb(i);
    sort(origin.begin(),origin.end(),cmp1);
    dfs(0,0,0);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
ll n,m,k;
ll ans=0;

unordered_map<ll,ll>M;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(ll deep,unordered_map<ll,ll>M)
{
    if(deep==k+1)
    {
        if(M.size()==n) ans++;
        M.clear();
        return ;
    }
    unordered_map<ll,ll>m;
    for(ll i=0;i<deep;i++)
    {
        m=M;
        for(ll j=0;j<sum[deep].size();j++)
        {
            ll to=sum[deep][j];
            m[field[to][i].to]=1;
        }
        dfs(deep+1,m);
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(ll i=1;i<=n;i++)
    {
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    dfs(1,M);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
vector<ll>hash1[10],hash2[10];
ll n,m,k;
ll ans=0;
ll tar;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(ll deep,ll tot1,ll tot2)
{
    if(deep==k+1)
    {
        if(tot1==n*(n+1)/2&&tot2==tar) ans++;
        return ;
    }
    for(ll i=0;i<deep;i++)
    {
        dfs(deep+1,tot1+hash1[deep][i],tot2+hash2[deep][i]);
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(ll i=1;i<=n;i++)
    {
        tar+=i*i-1;
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    for(ll i=1;i<=k;i++)
    {
        for(ll j=0;j<i;j++)
        {
            unordered_map<ll,ll>M;
            ll temp1=0,temp2=0;
            at(x,sum[i])
            {
                ll to=field[x][j].to;
                if(M.find(to)==M.end())
                {
                    temp1+=to;
                    temp2+=to*to-1;
                }
                M[to]=1;
            }
            hash1[i].pb(temp1);
            hash2[i].pb(temp2);
        }
    }
    dfs(1,0,0);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
bool flag[maxn];
ll n,m,k;
ll ans=0;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(ll deep)
{
    if(deep==k+1)
    {
        ans++;
        return ;
    }
    for(ll i=1;i<=deep;i++)
    {
        bool f=1;
        vector<ll>cas;
        for(ll j=0;j<sum[deep].size();j++)
        {
            ll to=sum[deep][j];
            if(flag[field[to][i-1].to])
            {
                f=0;
            }
            else
            {
                cas.pb(field[to][i-1].to);
                flag[field[to][i-1].to]=1;
            }
        }
        if(f) dfs(deep+1);
        at(x,cas) flag[x]=0;
        cas.clear();
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(ll i=1;i<=n;i++)
    {
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    dfs(1);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    int to,weight;
};

vector<Node>field[maxn];
vector<int>sum[10];
vector<int>origin;
bool flag[maxn];
int n,m,k;
int ans=0;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(int deep)
{
    if(deep==k)
    {
        ans++;
        return;
    }
    for(int i=1;i<=origin[deep];i++)
    {
        bool f=1;
        vector<int>cas;
        for(int j=0;j<sum[origin[deep]].size();j++)
        {
            int to=sum[origin[deep]][j];
            if(flag[field[to][i-1].to])
            {
                f=0;
            }
            else
            {
                cas.pb(field[to][i-1].to);
                flag[field[to][i-1].to]=1;
            }
        }
        if(f) dfs(deep+1);
        at(x,cas)
        {
            flag[x]=0;
        }
    }
}

bool cmp1(int a,int b)
{
    return sum[a].size()>sum[b].size();
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        int u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(int i=1;i<=n;i++)
    {
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    for(int i=1;i<=k;i++) origin.pb(i);
    sort(origin.begin(),origin.end(),cmp1);
    dfs(0);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
ll n,m,k;
ll ans=0;
ll tot1,tot2;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(ll deep,ll now1,ll now2)
{
    if(deep==k+1)
    {
        if(now1==tot1&&now2==tot2) ans++;
        return ;
    }
    for(ll i=0;i<deep;i++)
    {
        ll temp1=now1,temp2=now2;
        for(ll j=0;j<sum[deep].size();j++)
        {
            ll to=sum[deep][j];
            to=field[to][i].to;
            temp1+=to*to-1;
            temp2+=to*to-2;
        }
        dfs(deep+1,temp1,temp2);
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(ll i=1;i<=n;i++)
    {
        tot1+=i*i-1;
        tot2+=i*i-2;
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    dfs(1,0,0);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
ll n,m,k;
ll ans=0;
ll tot1,tot2;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(ll deep,ll now1,ll now2)
{
    if(deep==k+1)
    {
        if(now1==tot1&&now2==tot2) ans++;
        return ;
    }
    for(ll i=0;i<deep;i++)
    {
        ll temp1=now1,temp2=now2;
        for(ll j=0;j<sum[deep].size();j++)
        {
            ll to=sum[deep][j];
            to=field[to][i].to;
            temp1+=to*to-1;
            temp2+=to*to+1;
        }
        dfs(deep+1,temp1,temp2);
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(ll i=1;i<=n;i++)
    {
        tot1+=i*i-1;
        tot2+=i*i+1;
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    dfs(1,0,0);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
ll n,m,k;
ll ans=0;
ll tot1,tot2;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(ll deep,ll now1,ll now2)
{
    if(deep==k+1)
    {
        if(now1==tot1&&now2==tot2) ans++;
        return ;
    }
    for(ll i=0;i<deep;i++)
    {
        ll temp1=now1,temp2=now2;
        for(ll j=0;j<sum[deep].size();j++)
        {
            ll to=sum[deep][j];
            to=field[to][i].to;
            temp1+=to*to-1;
            temp2+=to*to*to-1;
        }
        dfs(deep+1,temp1,temp2);
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(ll i=1;i<=n;i++)
    {
        tot1+=i*i-1;
        tot2+=i*i*i-1;
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    dfs(1,0,0);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    int to,weight;
};

vector<Node>field[maxn];
vector<int>sum[10];
vector<int>origin;
bool flag[maxn];
int n,m,k;
int ans=0;
int tot=0;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(int deep)
{
    if(tot==n)
    {
        int temp=1;
        for(int i=deep;i<k;i++) temp*=origin[i];
        ans+=temp;
        return ;
    }
    for(int i=1;i<=origin[deep];i++)
    {
        bool f=1;
        vector<int>cas;
        for(int j=0;j<sum[origin[deep]].size();j++)
        {
            int to=sum[origin[deep]][j];
            if(flag[field[to][i-1].to])
            {
                f=0;
            }
            else
            {
                cas.pb(field[to][i-1].to);
                flag[field[to][i-1].to]=1;
                tot++;
            }
        }
        if(f) dfs(deep+1);
        at(x,cas)
        {
            flag[x]=0;
            tot--;
        }
    }
}

bool cmp1(int a,int b)
{
    return sum[a].size()>sum[b].size();
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        int u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(int i=1;i<=n;i++)
    {
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    for(int i=1;i<=k;i++) origin.pb(i);
    sort(origin.begin(),origin.end(),cmp1);
    dfs(0);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
ll n,m,k;
ll ans=0;
ll tot;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(ll deep,ll now)
{
    if(deep==k+1)
    {
        if(now==tot) ans++;
        return ;
    }
    for(ll i=0;i<deep;i++)
    {
        ll temp=now;
        for(ll j=0;j<sum[deep].size();j++)
        {
            ll to=sum[deep][j];
            to=field[to][i].to;
            temp+=to*to-1;
        }
        dfs(deep+1,temp);
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(ll i=1;i<=n;i++)
    {
        tot+=i*i-1;
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    dfs(1,0);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
vector<ll>hash1[10],hash2[10];
ll n,m,k;
ll ans=0;
ll tar1,tar2;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(ll deep,ll tot1,ll tot2)
{
    if(deep==k+1)
    {
        if(tot1==tar1&&tot2==tar2) ans++;
        return ;
    }
    for(ll i=0;i<deep;i++)
    {
        dfs(deep+1,tot1+hash1[deep][i],tot2+hash2[deep][i]);
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(ll i=1;i<=n;i++)
    {
        tar1+=i*i*i;
        tar2+=i*i;
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    for(ll i=1;i<=k;i++)
    {
        for(ll j=0;j<i;j++)
        {
            unordered_map<ll,ll>M;
            ll temp1=0,temp2=0;
            at(x,sum[i])
            {
                ll to=field[x][j].to;
                if(M.find(to)==M.end())
                {
                    temp1+=to*to*to;
                    temp2+=to*to;
                }
                M[to]=1;
            }
            hash1[i].pb(temp1);
            hash2[i].pb(temp2);
        }
    }
    dfs(1,0,0);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    int to,weight;
};

vector<Node>field[maxn];
vector<int>sum[10];
bool flag[maxn];
int n,m,k;
int ans=0;
int tot=0;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(int deep)
{
    if(tot==n)
    {
        int temp=1;
        for(int i=deep;i<=k;i++) temp*=i;
        ans+=temp;
        return ;
    }
    for(int i=1;i<=deep;i++)
    {
        bool f=1;
        vector<int>cas;
        for(int j=0;j<sum[deep].size();j++)
        {
            int to=sum[deep][j];
            if(flag[field[to][i-1].to])
            {
                f=0;
            }
            else
            {
                cas.pb(field[to][i-1].to);
                flag[field[to][i-1].to]=1;
                tot++;
            }
        }
        if(f) dfs(deep+1);
        at(x,cas)
        {
            flag[x]=0;
            tot--;
        }
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        int u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(int i=1;i<=n;i++)
    {
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    dfs(1);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e3+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
bool flag[maxn];
ll n,m,k;
ll ans=0;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(ll deep)
{
    if(deep==k+1)
    {
        ans++;
        return ;
    }
    for(ll i=1;i<=deep;i++)
    {
        bool f=1;
        vector<ll>cas;
        for(ll j=0;j<sum[deep].size();j++)
        {
            ll to=sum[deep][j];
            if(flag[field[to][i-1].to])
            {
                f=0;
            }
            else
            {
                cas.pb(field[to][i-1].to);
                flag[field[to][i-1].to]=1;
            }
        }
        if(f) dfs(deep+1);
        at(x,cas) flag[x]=0;
        cas.clear();
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(ll i=1;i<=n;i++)
    {
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    dfs(1);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
vector<ll>hash1[10],hash2[10];
ll n,m,k;
ll ans=0;
ll tar1,tar2;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(ll deep,ll tot1,ll tot2)
{
    if(deep==k+1)
    {
        if(tot1==tar1&&tot2==tar2) ans++;
        return ;
    }
    for(ll i=0;i<deep;i++)
    {
        dfs(deep+1,tot1+hash1[deep][i],tot2+hash2[deep][i]);
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(ll i=1;i<=n;i++)
    {
        tar1+=i*i*i-1;
        tar2+=i*i-1;
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    for(ll i=1;i<=k;i++)
    {
        for(ll j=0;j<i;j++)
        {
            unordered_map<ll,ll>M;
            ll temp1=0,temp2=0;
            at(x,sum[i])
            {
                ll to=field[x][j].to;
                if(M.find(to)==M.end())
                {
                    temp1+=to*to*to-1;
                    temp2+=to*to-1;
                }
                M[to]=1;
            }
            hash1[i].pb(temp1);
            hash2[i].pb(temp2);
        }
    }
    dfs(1,0,0);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
vector<ll>hash1[10],hash2[10];
ll n,m,k;
ll ans=0;
ll tar;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(ll deep,ll tot1,ll tot2)
{
    if(deep==k+1)
    {
        if(tot1==n*(n+1)/2&&tot2==tar) ans++;
        return ;
    }
    for(ll i=1;i<=deep;i++)
    {
        for(ll j=0;j<i;j++)
            dfs(deep+1,tot1+hash1[i][j],tot2+hash2[i][j]);
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(ll i=1;i<=n;i++)
    {
        tar+=i*i-1;
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    for(ll i=1;i<=k;i++)
    {
        for(ll j=0;j<i;j++)
        {
            unordered_map<ll,ll>M;
            ll temp1=0,temp2=0;
            at(x,sum[i])
            {
                ll to=field[x][j].to;
                if(M.find(to)==M.end())
                {
                    temp1+=to;
                    temp2+=to*to-1;
                }
                M[to]=1;
            }
            hash1[i].pb(temp1);
            hash2[i].pb(temp2);
        }
    }
    dfs(1,0,0);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    int to,weight;
};

vector<Node>field[maxn];
vector<int>sum[10];
bool flag[maxn];
int n,m,k;
int ans=0;
int tot=0;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(int deep)
{
    if(tot==n)
    {
        ans++;
        return ;
    }
    for(int i=1;i<=deep;i++)
    {
        bool f=1;
        vector<int>cas;
        for(int j=0;j<sum[deep].size();j++)
        {
            int to=sum[deep][j];
            if(flag[field[to][i-1].to])
            {
                f=0;
            }
            else
            {
                cas.pb(field[to][i-1].to);
                flag[field[to][i-1].to]=1;
                tot++;
            }
        }
        if(f) dfs(deep+1);
        at(x,cas)
        {
            flag[x]=0;
            tot--;
        }
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        int u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(int i=1;i<=n;i++)
    {
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    dfs(1);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
#include<unordered_map>
#include<unordered_set>
//#include<bits/stdc++.h>
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define ft first
#define sd second
#define endl "\n"
#define mp make_pair
#define pb push_back
#define ll long long
#define vec vector<ll>
#define mat vector<vector<ll>>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define _rep(i,n) for(ll i=n-1;i>=0;i--)
#define REP(i,n) for(ll i=1;i<=(ll)(n);i++)
#define _REP(i,n) for(ll i=n;i>0;i--)
#define at(x,n) for(auto &x:n)
//cout<<fixed<<setprecision(6)<<
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
//ifstream f1("/Users/wangzichao/Documents/wzc.in");
//ofstream f2("/Users/wangzichao/Documents/wzc.out");
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

int read()      //整数读入挂
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

using namespace std;
typedef pair<ll,ll> PLL;
#define local
#ifdef local
#endif
const ll maxn=2e5+7;
const double eps=1e-10;
const ll mod=1e9+7;

struct Node
{
    int to,weight;
};

vector<Node>field[maxn];
vector<int>sum[10];
bool flag[maxn];
int n,m,k;
int ans=0;
int tot=0;

bool cmp(Node a,Node b)
{
    return a.weight<b.weight;
}

void dfs(int deep)
{
    if(tot==n)
    {
        int temp=1;
        for(int i=deep+1;i<=k;i++) temp*=i;
        ans+=temp;
        return ;
    }
    for(int i=1;i<=deep;i++)
    {
        bool f=1;
        vector<int>cas;
        for(int j=0;j<sum[deep].size();j++)
        {
            int to=sum[deep][j];
            if(flag[field[to][i-1].to])
            {
                f=0;
            }
            else
            {
                cas.pb(field[to][i-1].to);
                flag[field[to][i-1].to]=1;
                tot++;
            }
        }
        if(f) dfs(deep+1);
        at(x,cas)
        {
            flag[x]=0;
            tot--;
        }
    }
}

int32_t main()
{
    IOS;
    cin>>n>>m>>k;
    rep(i,m)
    {
        int u,v,w;
        cin>>u>>v>>w;
        field[u].pb({v,w});
    }
    for(int i=1;i<=n;i++)
    {
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].pb(i);
    }
    dfs(1);
    cout<<ans<<endl;
}

//记得改回maxn!!!!!!!


#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define ll long long
#define pi pair<int,int>
#define pl pair<ll,ll>
#define pd pair<double,double>
#define ld long double
#define pld pair<ld,ld>
#define lg length()
#define sz size()
#define vi vector<int>
#define vl vector<ll>
#define vp vector<pi>
#define vpl vector<pl>
#define pb push_back
#define INF 1000000005
#define LINF 1000000000000000005
#define all(x) (x).begin(), (x).end()

int n,m,k,x,y,z,ans,a[10],b[10][10];

vector <pi> t[10][10],temp;
vector <pi> g[200005];
vector <int> h[200005];

void Gen(int p){
    if(p==k+1){
        ans++;
        return;
    }
    for(int i=1;i<=p;i++){
        if(!b[p][i]){
            a[p]=i;
            for(pi j : t[p][i]) b[j.x][j.y]++;
            Gen(p+1);
            for(pi j : t[p][i]) b[j.x][j.y]--;
        }
    }
}

int32_t main(){
    ios_base :: sync_with_stdio(0); cin.tie(); cout.tie();
#ifdef LOCAL_DEFINE
    ifstream cin("input.txt");
#endif
    cin >> n >> m >> k;
    for(int i=1;i<=m;i++){
        cin >> x >> y >> z;
        g[x].pb({z,y});
        h[y].pb(x);
    }
    for(int i=1;i<=n;i++) sort(all(g[i]));
    for(int i=1;i<=n;i++){
        temp.clear();
        for(int j : h[i]){
            for(int k=0;k<g[j].sz;k++){
                if(g[j][k].y==i){
                    temp.pb({g[j].sz,k+1});
                    break;
                }
            }
        }
        for(pi j : temp){
            b[j.x][j.y]--;
            for(pi k : temp){
                if(j.x<k.x) t[j.x][j.y].pb(k);
                if(k==j) b[j.x][j.y]++;
            }
        }
    }
    for(int i=1;i<=k;i++){
        for(int j=1;j<=i;j++){
            t[i][j].erase(unique(all(t[i][j])),t[i][j].end());
        }
    }
    Gen(1);
    cout << ans;
}


#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define ll long long
#define pi pair<int,int>
#define pl pair<ll,ll>
#define pd pair<double,double>
#define ld long double
#define pld pair<ld,ld>
#define lg length()
#define sz size()
#define vi vector<int>
#define vl vector<ll>
#define vp vector<pi>
#define vpl vector<pl>
#define pb push_back
#define INF 1000000005
#define LINF 1000000000000000005
#define all(x) (x).begin(), (x).end()

int n,m,k,x,y,z,ans,a[10],b[10][10][10][10];

vector <pi> t[10][10],temp[200005];
vector <pi> g[200005];
vector <int> h[200005];

void Gen(int p){
    if(p==k+1){
        for(int i=1;i<=k;i++){
            for(int j=i;j<=k;j++){
                if(b[i][a[i]][j][a[j]]) return;
            }
        }
        ans++;
        return;
    }
    for(int i=1;i<=p;i++){
        a[p]=i;
        Gen(p+1);
    }
}

int32_t main(){
    ios_base :: sync_with_stdio(0); cin.tie(); cout.tie();
#ifdef LOCAL_DEFINE
    ifstream cin("input.txt");
#endif
    cin >> n >> m >> k;
    for(int i=1;i<=m;i++){
        cin >> x >> y >> z;
        g[x].pb({z,y});
        h[y].pb(x);
    }
    for(int i=1;i<=n;i++) sort(all(g[i]));
    for(int i=1;i<=n;i++){
        for(int k=0;k<g[i].sz;k++){
            temp[g[i][k].y].pb({g[i].sz,k+1});
        }
    }
    for(int i=1;i<=n;i++){
        for(pi j : temp[i]){
            b[j.x][j.y][j.x][j.y]--;
            for(pi k : temp[i]){
                b[j.x][j.y][k.x][k.y]++;
            }
        }
    }
    Gen(1);
    cout << ans;
}


#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define ll long long
#define pi pair<int,int>
#define pl pair<ll,ll>
#define pd pair<double,double>
#define ld long double
#define pld pair<ld,ld>
#define lg length()
#define sz size()
#define vi vector<int>
#define vl vector<ll>
#define vp vector<pi>
#define vpl vector<pl>
#define pb push_back
#define INF 1000000005
#define LINF 1000000000000000005
#define all(x) (x).begin(), (x).end()

int n,m,k,x,y,z,ans,a[10],b[10][10][10][10];

vector <pi> t[10][10],temp;
vector <pi> g[200005];
vector <int> h[200005];

void Gen(int p){
    if(p==k+1){
        for(int i=1;i<=k;i++){
            for(int j=i;j<=k;j++){
                if(b[i][a[i]][j][a[j]]) return;
            }
        }
        ans++;
        return;
    }
    for(int i=1;i<=p;i++){
        a[p]=i;
        Gen(p+1);
    }
}

int32_t main(){
    ios_base :: sync_with_stdio(0); cin.tie(); cout.tie();
#ifdef LOCAL_DEFINE
    ifstream cin("input.txt");
#endif
    cin >> n >> m >> k;
    for(int i=1;i<=m;i++){
        cin >> x >> y >> z;
        g[x].pb({z,y});
        h[y].pb(x);
    }
    for(int i=1;i<=n;i++) sort(all(g[i]));
    for(int i=1;i<=n;i++){
        temp.clear();
        for(int j : h[i]){
            for(int k=0;k<g[j].sz;k++){
                if(g[j][k].y==i){
                    temp.pb({g[j].sz,k+1});
                    break;
                }
            }
        }
        for(pi j : temp){
            b[j.x][j.y][j.x][j.y]--;
            for(pi k : temp){
                b[j.x][j.y][k.x][k.y]++;
            }
        }
    }
    Gen(1);
    cout << ans;
}


#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define ll long long
#define pi pair<int,int>
#define pl pair<ll,ll>
#define pd pair<double,double>
#define ld long double
#define pld pair<ld,ld>
#define lg length()
#define sz size()
#define vi vector<int>
#define vl vector<ll>
#define vp vector<pi>
#define vpl vector<pl>
#define pb push_back
#define INF 1000000005
#define LINF 1000000000000000005
#define all(x) (x).begin(), (x).end()

int n,m,k,x,y,z,ans,a[10],b[10][10][10][10];

vector <pi> t[10][10],temp;
vector <pi> g[200005];
vector <int> h[200005];

void Gen(int p){
    if(p==k+1){
        for(int i=1;i<=p;i++){
            for(int j=i;j<=p;j++){
                if(b[i][a[i]][j][a[j]]) return;
            }
        }
        ans++;
        return;
    }
    for(int i=1;i<=p;i++){
        a[p]=i;
        Gen(p+1);
    }
}

int32_t main(){
    ios_base :: sync_with_stdio(0); cin.tie(); cout.tie();
#ifdef LOCAL_DEFINE
    ifstream cin("input.txt");
#endif
    cin >> n >> m >> k;
    for(int i=1;i<=m;i++){
        cin >> x >> y >> z;
        g[x].pb({z,y});
        h[y].pb(x);
    }
    for(int i=1;i<=n;i++) sort(all(g[i]));
    for(int i=1;i<=n;i++){
        temp.clear();
        for(int j : h[i]){
            for(int k=0;k<g[j].sz;k++){
                if(g[j][k].y==i){
                    temp.pb({g[j].sz,k+1});
                    break;
                }
            }
        }
        for(pi j : temp){
            b[j.x][j.y][j.x][j.y]--;
            for(pi k : temp){
                b[j.x][j.y][k.x][k.y]++;
            }
        }
    }
    Gen(1);
    cout << ans;
}