#include <bits/stdc++.h>
using namespace std;
#define INT_INF 0x3f3f3f3f
#define LL_INF 0x3f3f3f3f3f3f3f3f
#define D_INF numeric_limits<double>::infinity()
#define MIN(a, b) ((a) = min((a), (b)))
#define MAX(a, b) ((a) = max((a), (b)))
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define f first
#define s second
#define all(a) (a).begin(), (a).end()
#define For(i, a, b) for (auto i = (a); i < (b); i++)
#define FOR(i, b) For(i, 0, b)
#define Rev(i, a, b) for (auto i = (a); i > (b); i--)
#define REV(i, a) Rev(i, a, -1)
#define sz(a) ((int) (a).size())
#define nl '\n'
#define sp ' '
#define ll long long
#define ld long double
#define uint unsigned int
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pill pair<int, ll>
#define plli pair<ll, int>
#define pdd pair<double, double>
#define uset unordered_set
#define umap unordered_map
#define pq priority_queue
template<typename T> using minpq = pq<T, vector<T>, greater<T>>;
template<typename T> using maxpq = pq<T, vector<T>, less<T>>;
template<typename T1,typename T2,typename H1=hash<T1>,typename H2=hash<T2>>struct pair_hash{size_t operator()(const pair<T1,T2>&p)const{return 31*H1{}(p.first)+H2{}(p.second);}};

#define _bufferSize 4096
#define _maxNumLength 128
char _inputBuffer[_bufferSize+1],*_inputPtr=_inputBuffer,_outputBuffer[_bufferSize],_c,_sign,*_tempInputBuf=nullptr,_numBuf[_maxNumLength],_tempOutputBuf[_maxNumLength],_fill=' ';
const char*_delimiter=" ";int _cur,_outputPtr=0,_numPtr=0,_precision=6,_width=0,_tempOutputPtr=0,_cnt;ull _precisionBase=1000000;
#define _peekchar() (*_inputPtr?*_inputPtr:(_inputBuffer[fread(_inputPtr=_inputBuffer,1,_bufferSize,stdin)]='\0',*_inputPtr))
#define _getchar() (*_inputPtr?*_inputPtr++:(_inputBuffer[fread(_inputPtr=_inputBuffer,1,_bufferSize,stdin)]='\0',*_inputPtr++))
#define _hasNext() (*_inputPtr||!feof(stdin))
#define _readSignAndNum(x) do{(x)=_getchar();}while((x)<=' ');_sign=(x)=='-';if(_sign)(x)=_getchar();for((x)-='0';(_c=_getchar())>='0';(x)=(x)*10+_c-'0')
#define _readFloatingPoint(x,T) for(T _div=1.0;(_c=_getchar())>='0';(x)+=(_c-'0')/(_div*=10))
#define rc(x) do{do{(x)=_getchar();}while((x)<=' ');}while(0)
#define ri(x) do{_readSignAndNum(x);if(_sign)(x)=-(x);}while(0)
#define rd(x) do{_readSignAndNum(x);if(_c=='.')_readFloatingPoint(x,double);if(_sign)(x)=-(x);}while(0)
#define rld(x) do{_readSignAndNum(x);if(_c=='.')_readFloatingPoint(x,ld);if(_sign)(x)=-(x);}while(0)
#define rcs(x) do{_cur=0;do{_c=_getchar();}while(_c<=' ');do{(x)[_cur++]=_c;}while((_c=_getchar())>' ');(x)[_cur]='\0';}while(0)
#define rs(x) do{if(!_tempInputBuf)assert(0);rcs(_tempInputBuf);(x)=string(_tempInputBuf,_cur);}while(0)
#define rcln(x) do{_cur=0;do{_c=_getchar();}while(_c<=' ');do{(x)[_cur++]=_c;}while((_c=_getchar())>=' ');(x)[_cur]='\0';}while(0)
#define rln(x) do{if(!_tempInputBuf)assert(0);rcln(_tempInputBuf);(x)=string(_tempInputBuf,_cur);}while(0)
#define setLength(x) do{if(_tempInputBuf)delete[](_tempInputBuf);_tempInputBuf=new char[(x)+1];}while(0)
void read(int&x){ri(x);}void read(uint&x){ri(x);}void read(ll&x){ri(x);}void read(ull&x){ri(x);}void read(double&x){rd(x);}void read(ld&x){rld(x);}
void read(char&x){rc(x);}void read(char*x){rcs(x);}void read(string&x){rs(x);}bool hasNext(){while(_hasNext()&&_peekchar()<=' ')_getchar();return _hasNext();}
template<typename T,typename...Ts>void read(T&&x,Ts&&...xs){read(x);read(forward<Ts>(xs)...);}
#define _flush() do{_flushBuf();fflush(stdout);}while(0)
#define _flushBuf() (fwrite(_outputBuffer,1,_outputPtr,stdout),_outputPtr=0)
#define _putchar(x) (_outputBuffer[_outputPtr==_bufferSize?_flushBuf():_outputPtr]=(x),_outputPtr++)
#define _writeTempBuf(x) (_tempOutputBuf[_tempOutputPtr++]=(x))
#define _writeOutput() for(int _i=0;_i<_tempOutputPtr;_putchar(_tempOutputBuf[_i++]));_tempOutputPtr=0
#define _writeNum(x,T,digits) _cnt=0;for(T _y=(x);_y;_y/=10,_cnt++)_numBuf[_numPtr++]='0'+_y%10;for(;_cnt<digits;_cnt++)_numBuf[_numPtr++]='0';_flushNumBuf();
#define _writeFloatingPoint(x,T) ull _I=(ull)(x);ull _F=((x)-_I)*_precisionBase+(T)(0.5);if(_F>=_precisionBase){_I++;_F=0;}_writeNum(_I,ull,1);_writeTempBuf('.');_writeNum(_F,ull,_precision)
#define _checkFinite(x) if(std::isnan(x)){wcs("NaN");}else if(std::isinf(x)){wcs("Inf");}
#define _flushNumBuf() for(;_numPtr;_writeTempBuf(_numBuf[--_numPtr]))
#define _fillBuf(x) for(int _i=0;_i<(x);_i++)_putchar(_fill)
#define _flushTempBuf() int _tempLen=_tempOutputPtr;_fillBuf(_width-_tempLen);_writeOutput();_fillBuf(-_width-_tempLen)
#define wb(x) do{if(x)_writeTempBuf('1');else _writeTempBuf('0');_flushTempBuf();}while(0)
#define wc(x) do{_writeTempBuf(x); _flushTempBuf();}while(0)
#define wi(x) do{if((x)<0){_writeTempBuf('-');_writeNum(-(x),uint,1);}else{_writeNum(x,uint,1);}_flushTempBuf();}while(0)
#define wll(x) do{if((x)<0){_writeTempBuf('-');_writeNum(-(x),ull,1);}else{_writeNum(x,ull,1);}_flushTempBuf();}while(0)
#define wd(x) do{_checkFinite(x)else if((x)<0){_writeTempBuf('-');_writeFloatingPoint(-(x),double);}else{_writeFloatingPoint(x,double);}_flushTempBuf();}while(0)
#define wld(x) do{_checkFinite(x)else if((x)<0){_writeTempBuf('-');_writeFloatingPoint(-(x),ld);}else{_writeFloatingPoint(x,ld);}_flushTempBuf();}while(0)
#define wcs(x) do{int _slen=strlen(x);_fillBuf(_width-_slen);for(const char*_p=(x);*_p;_putchar(*_p++));_fillBuf(-_width-_slen);}while(0)
#define ws(x) do{_fillBuf(_width-(int)(x).length());for(int _i=0;_i<(int)(x).length();_putchar(x[_i++]));_fillBuf(-_width-(int)(x).length());}while(0)
#define setPrecision(x) do{_precision=(x);_precisionBase=1;for(int _i=0;_i<(x);_i++,_precisionBase*=10);}while(0)
#define setDelimiter(x) do{_delimiter=(x);}while(0)
#define setWidth(x) do{_width=(x);}while(0)
#define setFill(x) do{_fill=(x);}while(0)
void write(bool x){wb(x);}void write(int x){wi(x);}void write(uint x){wi(x);}void write(ll x){wll(x);}void write(ull x){wll(x);}void write(double x){wd(x);}void write(ld x){wld(x);}
void write(char x){wc(x);}void write(char*x){wcs(x);}void write(const char*x){wcs(x);}void write(string&x){ws(x);}
template<typename T,typename...Ts>void write(T&&x,Ts&&...xs){write(x);for(const char*_p=_delimiter;*_p;_putchar(*_p++));write(forward<Ts>(xs)...);}
void writeln(){_putchar('\n');}template<typename...Ts>void writeln(Ts&&...xs){write(forward<Ts>(xs)...);_putchar('\n');}
void flush(){_flush();}class IOManager{public:~IOManager(){flush();}};unique_ptr<IOManager>iomanager;

#define MAXN 5005

int N, Q, ***BIT;

void update(int a, int x, int y, int v) {
    for (int i = x; i <= N; i += i & -i) for (int j = y; j <= (a == 0 ? N : 2 * N); j += j & -j) BIT[a][i][j] += v;
}

int rsq(int a, int x, int y) {
    int sum = 0;
    for (int i = x; i > 0; i -= i & -i) for (int j = y; j > 0; j -= j & -j) sum += BIT[a][i][j];
    return sum;
}

int main() {
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    iomanager.reset(new IOManager());
    read(N, Q);
    BIT = new int**[3];
    FOR(i, 3) {
        BIT[i] = new int*[MAXN];
        FOR(j, N + 1) {
            if (i == 0) {
                BIT[i][j] = new int[MAXN];
                FOR(k, N + 1) BIT[i][j][k] = 0;
            } else {
                BIT[i][j] = new int[MAXN * 2];
                FOR(k, 2 * N + 1) BIT[i][j][k] = 0;
            }
        }
    }
    int t, d, x, y, L;
    FOR(q, Q) {
        read(t);
        if (t == 1) {
            read(d, x, y, L);
            if (L == 0) {
                update(0, x, y, 1);
                update(0, x + 1, y, -1);
                update(0, x, y + 1, -1);
                update(0, x + 1, y + 1, 1);
            } else if (d == 1) {
                update(0, x, y, 1);
                update(0, x + L + 1, y, -1);
                update(1, x, x + y + L + 1, -1);
                update(1, x + L + 1, x + y + L + 1, 1);
            } else if (d == 2) {
                update(0, x, y + 1, -1);
                update(0, x + L + 1, y + 1, 1);
                update(2, x, N - x + y - L, 1);
                update(2, x + L + 1, N - x + y - L, -1);
            } else if (d == 3) {
                update(0, x - L, y, 1);
                update(0, x + 1, y, -1);
                update(2, x - L, N - x + y + L + 1, -1);
                update(2, x + 1, N - x + y + L + 1, 1);
            } else {
                update(0, x - L, y + 1, -1);
                update(0, x + 1, y + 1, 1);
                update(1, x - L + 1, x + y - L + 1, 1);
                update(1, x + 1, x + y - L + 1, -1);
            }
        } else {
            read(x, y);
            writeln(rsq(0, x, y) + rsq(1, x, x + y) + rsq(2, x, N - x + y));
        }
    }
    return 0;
}


//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx2")
// 293206GT
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <unordered_set>
#include <stack>
#include <string>
#include<algorithm>
#include <random>
#include <bitset>
#include <chrono>

typedef long long ll;
//#define int ll
using namespace std;
#define put(a) cout << (a) << '\n'
#define sqr(x) (x) * (x)
typedef pair<int, int> pii;
typedef long double ld;
typedef pair<ld, ld> pld;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<pii> vpii;
#define rep(x, y, a) for (int x = (y); x < (int)(a); ++x)
#define all(a) a.begin(), a.end()
#define chkmax(a, b) a = max(a, (b))
#define chkmin(a, b) a = min(a, (b))

namespace IO {

    template<class A, class B>
    ostream &operator<<(ostream &out, vector<pair<A, B>> a);

    template<class A>
    ostream &operator<<(ostream &out, vector<A> a);

    template<class A, class B>
    ostream &operator<<(ostream &out, pair<A, B> a) {
        out << a.first << " " << a.second;
        return out;
    }

    template<class A, class B>
    ostream &operator<<(ostream &out, vector<pair<A, B>> a) {
        for (pair<A, B> x: a)
            out << x.first << " " << x.second << '\n';
        return out;
    }

    template<class A>
    ostream &operator<<(ostream &out, vector<A> a) {
        for (A x: a) out << x << ' ';
        return out;
    }

    template<class A, class B>
    istream &operator>>(istream &in, pair<A, B> &a) {
        in >> a.first >> a.second;
        return in;
    }

    template<class A>
    istream &operator>>(istream &in, vector<A> &a) {
        for (A &x: a) in >> x;
        return in;
    }
}
using namespace IO;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2e5 + 3;
vi g[N];
vi g2[N];
vi r_g[N];
int to[N];
const int K = 10;
int to2[N];
int can[K][K][K][K];
vpii I_AM_RETARDED[N];
void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    rep(i, 0, m) {
        int a, b, c;
        cin >> a >> b >> c;
        --a;--b;--c;
        r_g[b].push_back(c);
        g[a].push_back(c);
        to2[c] = b;
        to[c] = a;
    }
    vi pos(m);
    rep(i, 0,n)rep(j, 0, g[i].size()) pos[g[i][j]] = j;
    rep(i, 0, n) {
        int b = g[i].size() - 1;
        rep(j, 0, g[i].size()) {
            I_AM_RETARDED[to2[g[i][j]]].push_back({b, j});
        }
    }
    rep(i, 0, n) {
        set<pii> cur2;
        rep(j, 0, I_AM_RETARDED[i].size()) {
            if (cur2.count(I_AM_RETARDED[i][j])) {
                can[I_AM_RETARDED[i][j].first][I_AM_RETARDED[i][j].second][I_AM_RETARDED[i][j].first][I_AM_RETARDED[i][j].second] = 1;
            }
            cur2.insert(I_AM_RETARDED[i][j]);
        }
        vpii cur(all(cur2));
        rep(j, 0, cur.size()) rep(k, 0, cur.size()) {
            if (j == k) continue;
            int b = cur[j].first;
            int c = cur[k].first;
            int l1 = cur[j].second;
            int l2 = cur[k].second;
            can[b][l1][c][l2] = 1;
        }
    }
    vi cur(k, 0);
    int ans = 0;
    cur[k - 1] = -1;
    while (1) {
        int p = k - 1;
        while (p >= 0 && cur[p] == p) {
            cur[p] = 0;
            --p;
        }
        if (p == -1) break;
        ++cur[p];
        int f = 1;
        rep(i, 0, k) if (can[i][cur[i]][i][cur[i]]) {
            f = 0;
            break;
        }

        rep(i, 0, k) {
            if (!f) break;
            rep(j, i + 1, k) {
                if (can[i][cur[i]][j][cur[j]]) {
                    f = 0;
                    break;
                }
            }
        }
        ans += f;
    }
    put(ans);
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(30);
//    freopen("input.txt", "r", stdin);
    int q = 1;
//    cin >> q;

    while (q--) solve();
}


//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx2")
// 293206GT
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <unordered_set>
#include <stack>
#include <string>
#include<algorithm>
#include <random>
#include <bitset>
#include <chrono>

typedef long long ll;
//#define int ll
using namespace std;
#define put(a) cout << (a) << '\n'
#define sqr(x) (x) * (x)
typedef pair<int, int> pii;
typedef long double ld;
typedef pair<ld, ld> pld;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<pii> vpii;
#define rep(x, y, a) for (int x = (y); x < (int)(a); ++x)
#define all(a) a.begin(), a.end()
#define chkmax(a, b) a = max(a, (b))
#define chkmin(a, b) a = min(a, (b))

namespace IO {

    template<class A, class B>
    ostream &operator<<(ostream &out, vector<pair<A, B>> a);

    template<class A>
    ostream &operator<<(ostream &out, vector<A> a);

    template<class A, class B>
    ostream &operator<<(ostream &out, pair<A, B> a) {
        out << a.first << " " << a.second;
        return out;
    }

    template<class A, class B>
    ostream &operator<<(ostream &out, vector<pair<A, B>> a) {
        for (pair<A, B> x: a)
            out << x.first << " " << x.second << '\n';
        return out;
    }

    template<class A>
    ostream &operator<<(ostream &out, vector<A> a) {
        for (A x: a) out << x << ' ';
        return out;
    }

    template<class A, class B>
    istream &operator>>(istream &in, pair<A, B> &a) {
        in >> a.first >> a.second;
        return in;
    }

    template<class A>
    istream &operator>>(istream &in, vector<A> &a) {
        for (A &x: a) in >> x;
        return in;
    }
}
using namespace IO;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2e5 + 3;
vi g[N];
vi g2[N];
vi r_g[N];
int to[N];
const int K = 10;
int can[K][K][K][K];
void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    rep(i, 0, m) {
        int a, b, c;
        cin >> a >> b >> c;
        --a;--b;--c;
        r_g[b].push_back(c);
        g[a].push_back(c);
        to[c] = a;
    }
    rep(i, 0, n) sort(all(g[i]));
    vi pos(m);
    rep(i, 0,n)rep(j, 0, g[i].size()) pos[g[i][j]] = j;
    rep(i, 0, n) {
        rep(j, 0, r_g[i].size()) rep(k, 0, r_g[i].size()) {
            if (j == k) continue;
            int v1 = to[r_g[i][j]];
            int v2 = to[r_g[i][k]];
            int b = g[v1].size() - 1;
            int c = g[v2].size() - 1;
            int l1 = pos[r_g[i][j]];
            int l2 = pos[r_g[i][k]];
            can[b][l1][c][l2] = 1;
        }
    }
    vi cur(k, 0);
    int ans = 0;
    cur[k - 1] = -1;
    while (1) {
        int p = k - 1;
        while (p >= 0 && cur[p] == p) {
            cur[p] = 0;
            --p;
        }
        if (p == -1) break;
        ++cur[p];
        int f = 1;
        rep(i, 0, k) rep(j, cur[i], cur[i] + 1) if (can[i][j][i][j]) {
            f = 0;
            break;
        }

        rep(i, 0, k) {
            if (!f) break;
            rep(j, i + 1, k) {
                if (can[i][cur[i]][j][cur[j]]) {
                    f = 0;
                    break;
                }
            }
        }
        ans += f;
    }
    put(ans);
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(30);
//    freopen("input.txt", "r", stdin);
    int q = 1;
//    cin >> q;

    while (q--) solve();
}


//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx2")
// 293206GT
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <unordered_set>
#include <stack>
#include <string>
#include<algorithm>
#include <random>
#include <bitset>
#include <chrono>

typedef long long ll;
// #define int ll
using namespace std;
#define put(a) cout << (a) << '\n'
#define sqr(x) (x) * (x)
typedef pair<int, int> pii;
typedef long double ld;
typedef pair<ld, ld> pld;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<pii> vpii;
#define rep(x, y, a) for (int x = (y); x < (int)(a); ++x)
#define all(a) a.begin(), a.end()
#define chkmax(a, b) a = max(a, (b))
#define chkmin(a, b) a = min(a, (b))

namespace IO {

    template<class A, class B>
    ostream &operator<<(ostream &out, vector<pair<A, B>> a);

    template<class A>
    ostream &operator<<(ostream &out, vector<A> a);

    template<class A, class B>
    ostream &operator<<(ostream &out, pair<A, B> a) {
        out << a.first << " " << a.second;
        return out;
    }

    template<class A, class B>
    ostream &operator<<(ostream &out, vector<pair<A, B>> a) {
        for (pair<A, B> x: a)
            out << x.first << " " << x.second << '\n';
        return out;
    }

    template<class A>
    ostream &operator<<(ostream &out, vector<A> a) {
        for (A x: a) out << x << ' ';
        return out;
    }

    template<class A, class B>
    istream &operator>>(istream &in, pair<A, B> &a) {
        in >> a.first >> a.second;
        return in;
    }

    template<class A>
    istream &operator>>(istream &in, vector<A> &a) {
        for (A &x: a) in >> x;
        return in;
    }
}
using namespace IO;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2e5 + 3;
vi g[N];
vi r_g[N];
int to[N];
const int K = 10;
int can[K][K][K][K];
void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    rep(i, 0, m) {
        int a, b, c;
        cin >> a >> b >> c;
        --a;--b;--c;
        r_g[b].push_back(c);
        g[a].push_back(c);
        to[c] = a;
    }
    rep(i, 0, n) sort(all(g[i]));
    rep(i, 0, n) {
        rep(j, 0, r_g[i].size()) rep(k, 0, r_g[i].size()) {
            if (j == k) continue;
            int v1 = to[r_g[i][j]];
            int v2 = to[r_g[i][k]];
            int b = g[v1].size() - 1;
            int c = g[v2].size() - 1;
            int l1 = lower_bound(all(g[v1]), r_g[i][j]) - g[v1].begin();
            int l2 = lower_bound(all(g[v2]), r_g[i][k]) - g[v2].begin();
            can[b][l1][c][l2] = 1;
        }
    }
    vi cur(k, 0);
    int ans = 0;
    cur[k - 1] = -1;
    while (1) {
        int p = k - 1;
        while (p >= 0 && cur[p] == p) {
            cur[p] = 0;
            --p;
        }
        if (p == -1) break;
        ++cur[p];
        int f = 1;
        rep(i, 0, k) rep(j, cur[i], cur[i] + 1) if (can[i][j][i][j]) {
            f = 0;
            break;
        }

        rep(i, 0, k) {
            if (!f) break;
            rep(j, i + 1, k) {
                if (can[i][cur[i]][j][cur[j]]) {
                    f = 0;
                    break;
                }
            }
        }
        ans += f;
    }
    put(ans);
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(30);
//    freopen("input.txt", "r", stdin);
    int q = 1;
//    cin >> q;

    while (q--) solve();
}


//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx2")
// 293206GT
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <unordered_set>
#include <stack>
#include <string>
#include<algorithm>
#include <random>
#include <bitset>
#include <chrono>

typedef long long ll;
//#define int ll
using namespace std;
#define put(a) cout << (a) << '\n'
#define sqr(x) (x) * (x)
typedef pair<int, int> pii;
typedef long double ld;
typedef pair<ld, ld> pld;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<pii> vpii;
#define rep(x, y, a) for (int x = (y); x < (int)(a); ++x)
#define all(a) a.begin(), a.end()
#define chkmax(a, b) a = max(a, (b))
#define chkmin(a, b) a = min(a, (b))

namespace IO {

    template<class A, class B>
    ostream &operator<<(ostream &out, vector<pair<A, B>> a);

    template<class A>
    ostream &operator<<(ostream &out, vector<A> a);

    template<class A, class B>
    ostream &operator<<(ostream &out, pair<A, B> a) {
        out << a.first << " " << a.second;
        return out;
    }

    template<class A, class B>
    ostream &operator<<(ostream &out, vector<pair<A, B>> a) {
        for (pair<A, B> x: a)
            out << x.first << " " << x.second << '\n';
        return out;
    }

    template<class A>
    ostream &operator<<(ostream &out, vector<A> a) {
        for (A x: a) out << x << ' ';
        return out;
    }

    template<class A, class B>
    istream &operator>>(istream &in, pair<A, B> &a) {
        in >> a.first >> a.second;
        return in;
    }

    template<class A>
    istream &operator>>(istream &in, vector<A> &a) {
        for (A &x: a) in >> x;
        return in;
    }
}
using namespace IO;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2e5 + 3;
vi g[N];
vi g2[N];
vi r_g[N];
int to[N];
const int K = 10;
int can[K][K][K][K];
void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    rep(i, 0, m) {
        int a, b, c;
        cin >> a >> b >> c;
        --a;--b;--c;
        r_g[b].push_back(c);
        g[a].push_back(c);
        to[c] = a;
    }
    vi pos(m);
    rep(i, 0,n)rep(j, 0, g[i].size()) pos[g[i][j]] = j;
    rep(i, 0, n) {
        rep(j, 0, r_g[i].size()) rep(k, 0, r_g[i].size()) {
            if (j == k) continue;
            int v1 = to[r_g[i][j]];
            int v2 = to[r_g[i][k]];
            int b = g[v1].size() - 1;
            int c = g[v2].size() - 1;
            int l1 = pos[r_g[i][j]];
            int l2 = pos[r_g[i][k]];
            can[b][l1][c][l2] = 1;
        }
    }
    vi cur(k, 0);
    int ans = 0;
    cur[k - 1] = -1;
    while (1) {
        int p = k - 1;
        while (p >= 0 && cur[p] == p) {
            cur[p] = 0;
            --p;
        }
        if (p == -1) break;
        ++cur[p];
        int f = 1;
        rep(i, 0, k) rep(j, cur[i], cur[i] + 1) if (can[i][j][i][j]) {
            f = 0;
            break;
        }

        rep(i, 0, k) {
            if (!f) break;
            rep(j, i + 1, k) {
                if (can[i][cur[i]][j][cur[j]]) {
                    f = 0;
                    break;
                }
            }
        }
        ans += f;
    }
    put(ans);
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(30);
//    freopen("input.txt", "r", stdin);
    int q = 1;
//    cin >> q;

    while (q--) solve();
}


#include<bits/stdc++.h>
#define ALL(c) begin(c), end(c)
using namespace std;
using ll = long long;
using ld = long double;

const int N = 2e5+5;

vector<pair<int,int>> g[N], gi[N];

map<pair<int,int>,set<pair<int,int>>> block;

int ans = 0, c[11];
void go(int i, int h){
	if(i>h){
		++ans;
		return ;
	}

	for(c[i]=0;c[i]<i;++c[i]){
		bool ok = true;
		for(auto [j,x] : block[{i,c[i]}]){
			if(j<=i && c[j]==x) ok = false;
		}
		if(ok) go(i+1,h);
	}
}

int main(){
	//freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout);
	ios::sync_with_stdio(0);cin.tie(0);//cout.precision(12);cout<<fixed;

	int n,m,h;

	cin>>n>>m>>h;

	for(int w,i,j,k=0;k<m;++k){
		cin>>i>>j>>w;
		g[i].push_back({w,j});
		gi[j].push_back({w,i});
	}

	for(int i=1;i<=n;++i) sort(ALL(g[i]));

	for(int v=1;v<=n;++v){
		set<pair<int,int>> r;
		for(auto [w,x] : gi[v]){
			for(int l=0;l<size(g[x]);++l){
				if(g[x][l].first == w){
					pair<int,int> p(size(g[x]),l);
					if(r.count(p)){
						block[p].insert(p);
					}else r.insert(p);
					break;
				}
			}
		}

		for(auto ri : r)
		for(auto rj : r) if(ri!=rj){
			block[ri].insert(rj);
			//cout<<"!"<<r[i].first<<' '<<r[i].second<<' '<<r[j].first<<' '<<r[j].second<<endl;
		}
	}

	go(1,h);

	cout<<ans<<endl;

	return 0;
}


#include<bits/stdc++.h>
#define ALL(c) begin(c), end(c)
using namespace std;
using ll = long long;
using ld = long double;

const int N = 2e5+5;

vector<pair<int,int>> g[N], gi[N];

bool block[11][11][11][11];

int ans = 0, c[11];
void go(int i, int h){
	if(i>h){
		++ans;
		return ;
	}

	for(c[i]=0;c[i]<i;++c[i]){
		bool ok = true;
		for(int j=1;j<=i;++j)
		for(int x=0;x<j;++x) if(block[i][c[i]][j][x]){
			if(j<=i && c[j]==x) ok = false;
		}
		if(ok) go(i+1,h);
	}
}

int main(){
	//freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout);
	ios::sync_with_stdio(0);cin.tie(0);//cout.precision(12);cout<<fixed;

	int n,m,h;

	cin>>n>>m>>h;

	for(int w,i,j,k=0;k<m;++k){
		cin>>i>>j>>w;
		g[i].push_back({w,j});
		gi[j].push_back({w,i});
	}

	for(int i=1;i<=n;++i) sort(ALL(g[i]));

	for(int v=1;v<=n;++v){
		set<pair<int,int>> r;
		for(auto [w,x] : gi[v]){
			for(int l=0;l<size(g[x]);++l){
				if(g[x][l].first == w){
					pair<int,int> p(size(g[x]),l);
					if(r.count(p)){
						block[p.first][p.second][p.first][p.second] = 1;
					}else r.insert(p);
					break;
				}
			}
		}

		for(auto ri : r)
		for(auto rj : r) if(ri!=rj){
			block[ri.first][ri.second][rj.first][rj.second] = 1;
		}

	}

	go(1,h);

	cout<<ans<<endl;

	return 0;
}


#include<bits/stdc++.h>
#define ALL(c) begin(c), end(c)
using namespace std;
using ll = long long;
using ld = long double;

const int N = 2e5+5;

vector<pair<int,int>> g[N], gi[N];

set<pair<int,int>> block[11][11];

int ans = 0, c[11];
void go(int i, int h){
	if(i>h){
		++ans;
		return ;
	}

	for(c[i]=0;c[i]<i;++c[i]){
		bool ok = true;
		for(auto [j,x] : block[i][c[i]]){
			if(j<=i && c[j]==x) ok = false;
		}
		if(ok) go(i+1,h);
	}
}

int main(){
	//freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout);
	ios::sync_with_stdio(0);cin.tie(0);//cout.precision(12);cout<<fixed;

	int n,m,h;

	cin>>n>>m>>h;

	for(int w,i,j,k=0;k<m;++k){
		cin>>i>>j>>w;
		g[i].push_back({w,j});
		gi[j].push_back({w,i});
	}

	for(int i=1;i<=n;++i) sort(ALL(g[i]));

	for(int v=1;v<=n;++v){
		set<pair<int,int>> r;
		for(auto [w,x] : gi[v]){
			for(int l=0;l<size(g[x]);++l){
				if(g[x][l].first == w){
					pair<int,int> p(size(g[x]),l);
					if(r.count(p)){
						block[p.first][p.second].insert(p);
					}else r.insert(p);
					break;
				}
			}
		}

		for(auto ri : r)
		for(auto rj : r) if(ri!=rj){
			block[ri.first][ri.second].insert(rj);
			//cout<<"!"<<r[i].first<<' '<<r[i].second<<' '<<r[j].first<<' '<<r[j].second<<endl;
		}
	}

	go(1,h);

	cout<<ans<<endl;

	return 0;
}


#include<bits/stdc++.h>
#define ALL(c) begin(c), end(c)
using namespace std;
using ll = long long;
using ld = long double;

const int N = 2e5+5;

vector<pair<int,int>> g[N], gi[N];

bool block[11][11][11][11];

int ans = 0, c[11];
void go(int i, int h){
	if(i>h){
		++ans;
		return ;
	}

	for(c[i]=0;c[i]<i;++c[i]){
		bool ok = true;
		for(int j=1;j<=i;++j)
		for(int x=0;x<j;++x) if(block[i][c[i]][j][x]){
			if(j<=i && c[j]==x) ok = false;
		}
		if(ok) go(i+1,h);
	}
}

int main(){
	//freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout);
	ios::sync_with_stdio(0);cin.tie(0);//cout.precision(12);cout<<fixed;

	int n,m,h;

	cin>>n>>m>>h;

	for(int w,i,j,k=0;k<m;++k){
		cin>>i>>j>>w;
		g[i].push_back({w,j});
		gi[j].push_back({w,i});
	}

	for(int i=1;i<=n;++i) sort(ALL(g[i]));

	for(int v=1;v<=n;++v){
		set<pair<int,int>> r;
		for(auto [w,x] : gi[v]){
			for(int l=0;l<size(g[x]);++l){
				if(g[x][l].first == w){
					pair<int,int> p(size(g[x]),l);
					if(r.count(p)){
						cout<<0<<endl;
						return 0;
					}
					r.insert(p);
					break;
				}
			}
		}

		for(auto ri : r)
		for(auto rj : r) if(ri!=rj){
			block[ri.first][ri.second][rj.first][rj.second] = 1;
		}

	}

	go(1,h);

	cout<<ans<<endl;

	return 0;
}


#include<bits/stdc++.h>
#define ALL(c) begin(c), end(c)
using namespace std;
using ll = long long;
using ld = long double;

const int N = 2e5+5;

vector<pair<int,int>> g[N], gi[N];

set<pair<int,int>> block[11][11];

int ans = 0, c[11];
void go(int i, int h){
	if(i>h){
		++ans;
		return ;
	}

	for(c[i]=0;c[i]<i;++c[i]){
		bool ok = true;
		for(auto [j,x] : block[i][c[i]]){
			if(j<=i && c[j]==x) ok = false;
		}
		if(ok) go(i+1,h);
	}
}

int main(){
	//freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout);
	ios::sync_with_stdio(0);cin.tie(0);//cout.precision(12);cout<<fixed;

	int n,m,h;

	cin>>n>>m>>h;

	for(int w,i,j,k=0;k<m;++k){
		cin>>i>>j>>w;
		g[i].push_back({w,j});
		gi[j].push_back({w,i});
	}

	for(int i=1;i<=n;++i) sort(ALL(g[i]));

	for(int v=1;v<=n;++v){
		vector<pair<int,int>> r;
		for(auto [w,x] : gi[v]){
			for(int l=0;l<size(g[x]);++l){
				if(g[x][l].first == w){
					r.push_back({size(g[x]),l});
					break;
				}
			}
		}

		for(int i=0;i<size(r);++i)
		for(int j=0;j<size(r);++j) if(i!=j){
			block[r[i].first][r[i].second].insert(r[j]);
			//cout<<"!"<<r[i].first<<' '<<r[i].second<<' '<<r[j].first<<' '<<r[j].second<<endl;
		}
	}

	go(1,h);

	cout<<ans<<endl;

	return 0;
}


#include<bits/stdc++.h>
#define ALL(c) begin(c), end(c)
using namespace std;
using ll = long long;
using ld = long double;

const int N = 2e5+5;

vector<pair<int,int>> g[N], gi[N];

bool block[11][11][11][11];

int ans = 0, c[11];
void go(int i, int h){
	if(i>h){
		++ans;
		return ;
	}

	for(c[i]=0;c[i]<i;++c[i]){
		bool ok = true;
		for(int j=1;j<=i;++j)
		for(int x=0;x<j;++x) if(block[i][c[i]][j][x]){
			if(j<=i && c[j]==x) ok = false;
		}
		if(ok) go(i+1,h);
	}
}

int main(){
	//freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout);
	ios::sync_with_stdio(0);cin.tie(0);//cout.precision(12);cout<<fixed;

	int n,m,h;

	cin>>n>>m>>h;

	for(int w,i,j,k=0;k<m;++k){
		cin>>i>>j>>w;
		g[i].push_back({w,j});
		gi[j].push_back({w,i});
	}

	for(int i=1;i<=n;++i) sort(ALL(g[i]));

	for(int v=1;v<=n;++v){
		vector<pair<int,int>> r;
		for(auto [w,x] : gi[v]){
			for(int l=0;l<size(g[x]);++l){
				if(g[x][l].first == w){
					r.push_back({size(g[x]),l});
					break;
				}
			}
		}

		for(int i=0;i<size(r);++i)
		for(int j=0;j<size(r);++j) if(i!=j){
			block[r[i].first][r[i].second][r[j].first][r[j].second] = 1;
			//cout<<"!"<<r[i].first<<' '<<r[i].second<<' '<<r[j].first<<' '<<r[j].second<<endl;
		}
	}

	go(1,h);

	cout<<ans<<endl;

	return 0;
}


#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <bits/stdc++.h>

using namespace __gnu_pbds;
using namespace std;

using ll = long long;
using ld = long double;

#define mp make_pair

typedef tree<
        pair<int, int>,
        null_type,
        less<pair<int, int>>,
        rb_tree_tag,
        tree_order_statistics_node_update>
        ordered_set;

const int p = 1000000007;

int mul(int a, int b) {
    return (1LL * a * b) % p;
}

int add(int a, int b) {
    int s = (a+b);
    if (s>=p) s-=p;
    return s;
}

int sub(int a, int b) {
    int s = (a+p-b);
    if (s>=p) s-=p;
    return s;
}

int po(int a, int deg)
{
    if (deg==0) return 1;
    if (deg%2==1) return mul(a, po(a, deg-1));
    int t = po(a, deg/2);
    return mul(t, t);
}

int inv(int n)
{
    return po(n, p-2);
}

mt19937 rnd(time(0));

/*
const int N = 1200000;

vector<int> facs(N), invfacs(N);

void init()
{
    facs[0] = 1;
    for (int i = 1; i<N; i++) facs[i] = mul(facs[i-1], i);
    invfacs[N-1] = inv(facs[N-1]);
    for (int i = N-2; i>=0; i--) invfacs[i] = mul(invfacs[i+1], i+1);
}

int C(int n, int k)
{
    if (n<k) return 0;
    return mul(facs[n], mul(invfacs[k], invfacs[n-k]));
}
*/

vector<vector<pair<int, int>>> G;

const int N = 10;

vector<vector<bitset<N>>> dp;
vector<vector<bool>> can;

ll res = 0;

int n, m, k;

vector<vector<vector<vector<bool>>>> check;

void recurse(vector<int> tmp)
{
    /*cout<<"recursing:"<<endl;
    for (auto it: tmp) cout<<it<<' ';
    cout<<endl;*/
    int cur = tmp.size();
    if (cur==k)
    {
        res++; return;
    }
    for (int cntcur = 0; cntcur<=cur; cntcur++)
    {
        bool ok = true;
        for (int i = 0; i<cur; i++) if (!check[i][cur][tmp[i]][cntcur])
        {
            ok = false; break;
        }
        if (ok)
        {
            vector<int> tmp1(tmp); tmp1.push_back(cntcur);
            recurse(tmp1);
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(nullptr);
    cin>>n>>m>>k;
    G.resize(n);
    for (int i = 0; i<m; i++)
    {
        int u, v, w;
        cin>>u>>v>>w;
        u--; v--;
        G[u].push_back(mp(w, v));
    }

    for (int i = 0; i<n; i++) sort(G[i].begin(), G[i].end());

    for (int i = 0; i<k; i++)
    {
        dp.push_back(vector<bitset<N>>(i+1));
        can.push_back(vector<bool>(i+1, true));
    }

    for (int i = 0; i<n; i++)
    {
        int deg = G[i].size();
        for (int j = 0; j<deg; j++)
        {
            if (dp[deg-1][j][G[i][j].second] == 1) can[deg-1][j] = false;
            else dp[deg-1][j][G[i][j].second] = 1;
        }
    }

    check = vector<vector<vector<vector<bool>>>>(k, vector<vector<vector<bool>>>(k, vector<vector<bool>>(k, vector<bool>(k))));

    for (int i = 0; i<k; i++)
        for (int j = i+1; j<k; j++)
        {
            for (int cnti = 0; cnti<=i; cnti++) if (can[i][cnti])
                for (int cntj = 0; cntj<=j; cntj++) if (can[j][cntj])
                {
                    if ((dp[i][cnti]&dp[j][cntj]).count() == 0) check[i][j][cnti][cntj] = true;
                }
        }

    /*for (int i = 0; i<k; i++)
    {
        cout<<i<<":"<<endl;
        for (auto it: dp[i]) cout<<it<<endl;
    }*/

    recurse({});
    cout<<res<<endl;

    //cout<<check[0][1][0][1]<<endl;

}


#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <bits/stdc++.h>

using namespace __gnu_pbds;
using namespace std;

using ll = long long;
using ld = long double;

#define mp make_pair

typedef tree<
        pair<int, int>,
        null_type,
        less<pair<int, int>>,
        rb_tree_tag,
        tree_order_statistics_node_update>
        ordered_set;

const int p = 1000000007;

int mul(int a, int b) {
    return (1LL * a * b) % p;
}

int add(int a, int b) {
    int s = (a+b);
    if (s>=p) s-=p;
    return s;
}

int sub(int a, int b) {
    int s = (a+p-b);
    if (s>=p) s-=p;
    return s;
}

int po(int a, int deg)
{
    if (deg==0) return 1;
    if (deg%2==1) return mul(a, po(a, deg-1));
    int t = po(a, deg/2);
    return mul(t, t);
}

int inv(int n)
{
    return po(n, p-2);
}

mt19937 rnd(time(0));

/*
const int N = 1200000;

vector<int> facs(N), invfacs(N);

void init()
{
    facs[0] = 1;
    for (int i = 1; i<N; i++) facs[i] = mul(facs[i-1], i);
    invfacs[N-1] = inv(facs[N-1]);
    for (int i = N-2; i>=0; i--) invfacs[i] = mul(invfacs[i+1], i+1);
}

int C(int n, int k)
{
    if (n<k) return 0;
    return mul(facs[n], mul(invfacs[k], invfacs[n-k]));
}
*/

vector<vector<pair<int, int>>> G;

const int N = 6;

vector<vector<bitset<N>>> dp;
vector<vector<bool>> can;

ll res = 0;

int n, m, k;

void recurse(int cur, bitset<N> bad)
{
    if (cur==k) {res++; return;}
    for (int i = 0; i<=cur; i++) if (can[cur][i])
    {
        if ((bad&dp[cur][i]).count()) continue;
        else
        {
            bitset<N> temp = (bad|dp[cur][i]);
            recurse(cur+1, temp);
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(nullptr);
    cin>>n>>m>>k;
    G.resize(n);
    for (int i = 0; i<m; i++)
    {
        int u, v, w;
        cin>>u>>v>>w;
        u--; v--;
        G[u].push_back(mp(w, v));
    }

    for (int i = 0; i<n; i++) sort(G[i].begin(), G[i].end());

    for (int i = 0; i<k; i++)
    {
        dp.push_back(vector<bitset<N>>(i+1));
        can.push_back(vector<bool>(i+1, true));
    }

    for (int i = 0; i<n; i++)
    {
        int deg = G[i].size();
        for (int j = 0; j<deg; j++)
        {
            if (dp[deg-1][j][G[i][j].second] == 1) can[deg-1][j] = false;
            else dp[deg-1][j][G[i][j].second] = 1;
        }
    }

    //for (int i = 0; i<n; i++) cout<<i<<": "<<G[i].size()<<endl;

    bitset<N> clean;
    recurse(0, clean);
    cout<<res<<endl;

    /*for (int i = 0; i<k; i++)
    {
        cout<<i<<": "<<endl;
        for (auto it: dp[i]) cout<<it<<endl;
    }*/

}


#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <bits/stdc++.h>

using namespace __gnu_pbds;
using namespace std;

using ll = long long;
using ld = long double;

#define mp make_pair

typedef tree<
        pair<int, int>,
        null_type,
        less<pair<int, int>>,
        rb_tree_tag,
        tree_order_statistics_node_update>
        ordered_set;

const int p = 1000000007;

int mul(int a, int b) {
    return (1LL * a * b) % p;
}

int add(int a, int b) {
    int s = (a+b);
    if (s>=p) s-=p;
    return s;
}

int sub(int a, int b) {
    int s = (a+p-b);
    if (s>=p) s-=p;
    return s;
}

int po(int a, int deg)
{
    if (deg==0) return 1;
    if (deg%2==1) return mul(a, po(a, deg-1));
    int t = po(a, deg/2);
    return mul(t, t);
}

int inv(int n)
{
    return po(n, p-2);
}

mt19937 rnd(time(0));

/*
const int N = 1200000;

vector<int> facs(N), invfacs(N);

void init()
{
    facs[0] = 1;
    for (int i = 1; i<N; i++) facs[i] = mul(facs[i-1], i);
    invfacs[N-1] = inv(facs[N-1]);
    for (int i = N-2; i>=0; i--) invfacs[i] = mul(invfacs[i+1], i+1);
}

int C(int n, int k)
{
    if (n<k) return 0;
    return mul(facs[n], mul(invfacs[k], invfacs[n-k]));
}
*/

vector<vector<pair<int, int>>> G;

const int N = 200000;

vector<vector<bitset<N>>> dp;
vector<vector<bool>> can;

ll res = 0;

int n, m, k;

vector<vector<vector<vector<bool>>>> check;

void recurse(vector<int> tmp)
{
    /*cout<<"recursing:"<<endl;
    for (auto it: tmp) cout<<it<<' ';
    cout<<endl;*/
    int cur = tmp.size();
    if (cur==k)
    {
        res++; return;
    }
    for (int cntcur = 0; cntcur<=cur; cntcur++) if (can[cur][cntcur])
    {
        bool ok = true;
        for (int i = 0; i<cur; i++) if (!check[i][cur][tmp[i]][cntcur])
        {
            ok = false; break;
        }
        if (ok)
        {
            vector<int> tmp1(tmp); tmp1.push_back(cntcur);
            recurse(tmp1);
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(nullptr);
    cin>>n>>m>>k;
    G.resize(n);
    for (int i = 0; i<m; i++)
    {
        int u, v, w;
        cin>>u>>v>>w;
        u--; v--;
        G[u].push_back(mp(w, v));
    }

    for (int i = 0; i<n; i++) sort(G[i].begin(), G[i].end());

    for (int i = 0; i<k; i++)
    {
        dp.push_back(vector<bitset<N>>(i+1));
        can.push_back(vector<bool>(i+1, true));
    }

    for (int i = 0; i<n; i++)
    {
        int deg = G[i].size();
        for (int j = 0; j<deg; j++)
        {
            if (dp[deg-1][j][G[i][j].second] == 1) can[deg-1][j] = false;
            else dp[deg-1][j][G[i][j].second] = 1;
        }
    }

    check = vector<vector<vector<vector<bool>>>>(k, vector<vector<vector<bool>>>(k, vector<vector<bool>>(k, vector<bool>(k))));

    for (int i = 0; i<k; i++)
        for (int j = i+1; j<k; j++)
        {
            for (int cnti = 0; cnti<=i; cnti++) if (can[i][cnti])
                for (int cntj = 0; cntj<=j; cntj++) if (can[j][cntj])
                {
                    if ((dp[i][cnti]&dp[j][cntj]).count() == 0) check[i][j][cnti][cntj] = true;
                }
        }

    /*for (int i = 0; i<k; i++)
    {
        cout<<i<<":"<<endl;
        for (auto it: dp[i]) cout<<it<<endl;
    }*/

    recurse({});
    cout<<res<<endl;

    //cout<<check[0][1][0][1]<<endl;

}


#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <bits/stdc++.h>

using namespace __gnu_pbds;
using namespace std;

using ll = long long;
using ld = long double;

#define mp make_pair

typedef tree<
        pair<int, int>,
        null_type,
        less<pair<int, int>>,
        rb_tree_tag,
        tree_order_statistics_node_update>
        ordered_set;

const int p = 1000000007;

int mul(int a, int b) {
    return (1LL * a * b) % p;
}

int add(int a, int b) {
    int s = (a+b);
    if (s>=p) s-=p;
    return s;
}

int sub(int a, int b) {
    int s = (a+p-b);
    if (s>=p) s-=p;
    return s;
}

int po(int a, int deg)
{
    if (deg==0) return 1;
    if (deg%2==1) return mul(a, po(a, deg-1));
    int t = po(a, deg/2);
    return mul(t, t);
}

int inv(int n)
{
    return po(n, p-2);
}

mt19937 rnd(time(0));

/*
const int N = 1200000;

vector<int> facs(N), invfacs(N);

void init()
{
    facs[0] = 1;
    for (int i = 1; i<N; i++) facs[i] = mul(facs[i-1], i);
    invfacs[N-1] = inv(facs[N-1]);
    for (int i = N-2; i>=0; i--) invfacs[i] = mul(invfacs[i+1], i+1);
}

int C(int n, int k)
{
    if (n<k) return 0;
    return mul(facs[n], mul(invfacs[k], invfacs[n-k]));
}
*/

vector<vector<pair<int, int>>> G;

const int N = 200000;

vector<vector<bitset<N>>> dp;
vector<vector<bool>> can;

ll res = 0;

int n, m, k;

void recurse(int cur, bitset<N> bad)
{
    if (cur==k) {res++; return;}
    for (int i = 0; i<=cur; i++) if (can[cur][i])
    {
        if ((bad&dp[cur][i]).count()) continue;
        else
        {
            bitset<N> temp = (bad|dp[cur][i]);
            recurse(cur+1, temp);
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(nullptr);
    cin>>n>>m>>k;
    G.resize(n);
    for (int i = 0; i<m; i++)
    {
        int u, v, w;
        cin>>u>>v>>w;
        u--; v--;
        G[u].push_back(mp(w, v));
    }

    for (int i = 0; i<n; i++) sort(G[i].begin(), G[i].end());

    for (int i = 0; i<k; i++)
    {
        dp.push_back(vector<bitset<N>>(i+1));
        can.push_back(vector<bool>(i+1, true));
    }

    for (int i = 0; i<n; i++)
    {
        int deg = G[i].size();
        for (int j = 0; j<deg; j++)
        {
            if (dp[deg-1][j][G[i][j].second] == 1) can[deg-1][j] = false;
            else dp[deg-1][j][G[i][j].second] = 1;
        }
    }

    //for (int i = 0; i<n; i++) cout<<i<<": "<<G[i].size()<<endl;

    bitset<N> clean;
    recurse(0, clean);
    cout<<res<<endl;

    /*for (int i = 0; i<k; i++)
    {
        cout<<i<<": "<<endl;
        for (auto it: dp[i]) cout<<it<<endl;
    }*/

}


#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <bits/stdc++.h>

using namespace __gnu_pbds;
using namespace std;

using ll = long long;
using ld = long double;

#define mp make_pair

typedef tree<
        pair<int, int>,
        null_type,
        less<pair<int, int>>,
        rb_tree_tag,
        tree_order_statistics_node_update>
        ordered_set;

const int p = 1000000007;

int mul(int a, int b) {
    return (1LL * a * b) % p;
}

int add(int a, int b) {
    int s = (a+b);
    if (s>=p) s-=p;
    return s;
}

int sub(int a, int b) {
    int s = (a+p-b);
    if (s>=p) s-=p;
    return s;
}

int po(int a, int deg)
{
    if (deg==0) return 1;
    if (deg%2==1) return mul(a, po(a, deg-1));
    int t = po(a, deg/2);
    return mul(t, t);
}

int inv(int n)
{
    return po(n, p-2);
}

mt19937 rnd(time(0));

/*
const int N = 1200000;

vector<int> facs(N), invfacs(N);

void init()
{
    facs[0] = 1;
    for (int i = 1; i<N; i++) facs[i] = mul(facs[i-1], i);
    invfacs[N-1] = inv(facs[N-1]);
    for (int i = N-2; i>=0; i--) invfacs[i] = mul(invfacs[i+1], i+1);
}

int C(int n, int k)
{
    if (n<k) return 0;
    return mul(facs[n], mul(invfacs[k], invfacs[n-k]));
}
*/

vector<vector<pair<int, int>>> G;

const int N = 10;

vector<vector<bitset<N>>> dp;
vector<vector<bool>> can;

ll res = 0;

int n, m, k;

vector<vector<vector<vector<bool>>>> check;

void recurse(vector<int> tmp)
{
    /*cout<<"recursing:"<<endl;
    for (auto it: tmp) cout<<it<<' ';
    cout<<endl;*/
    int cur = tmp.size();
    if (cur==k)
    {
        res++; return;
    }
    for (int cntcur = 0; cntcur<=cur; cntcur++) if (can[cur][cntcur])
    {
        bool ok = true;
        for (int i = 0; i<cur; i++) if (!check[i][cur][tmp[i]][cntcur])
        {
            ok = false; break;
        }
        if (ok)
        {
            vector<int> tmp1(tmp); tmp1.push_back(cntcur);
            recurse(tmp1);
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(nullptr);
    cin>>n>>m>>k;
    G.resize(n);
    for (int i = 0; i<m; i++)
    {
        int u, v, w;
        cin>>u>>v>>w;
        u--; v--;
        G[u].push_back(mp(w, v));
    }

    for (int i = 0; i<n; i++) sort(G[i].begin(), G[i].end());

    for (int i = 0; i<k; i++)
    {
        dp.push_back(vector<bitset<N>>(i+1));
        can.push_back(vector<bool>(i+1, true));
    }

    for (int i = 0; i<n; i++)
    {
        int deg = G[i].size();
        for (int j = 0; j<deg; j++)
        {
            if (dp[deg-1][j][G[i][j].second] == 1) can[deg-1][j] = false;
            else dp[deg-1][j][G[i][j].second] = 1;
        }
    }

    check = vector<vector<vector<vector<bool>>>>(k, vector<vector<vector<bool>>>(k, vector<vector<bool>>(k, vector<bool>(k))));

    for (int i = 0; i<k; i++)
        for (int j = i+1; j<k; j++)
        {
            for (int cnti = 0; cnti<=i; cnti++) if (can[i][cnti])
                for (int cntj = 0; cntj<=j; cntj++) if (can[j][cntj])
                {
                    if ((dp[i][cnti]&dp[j][cntj]).count() == 0) check[i][j][cnti][cntj] = true;
                }
        }

    /*for (int i = 0; i<k; i++)
    {
        cout<<i<<":"<<endl;
        for (auto it: dp[i]) cout<<it<<endl;
    }*/

    recurse({});
    cout<<res<<endl;

    //cout<<check[0][1][0][1]<<endl;

}


#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <bits/stdc++.h>

using namespace __gnu_pbds;
using namespace std;

using ll = long long;
using ld = long double;

#define mp make_pair

typedef tree<
        pair<int, int>,
        null_type,
        less<pair<int, int>>,
        rb_tree_tag,
        tree_order_statistics_node_update>
        ordered_set;

const int p = 1000000007;

int mul(int a, int b) {
    return (1LL * a * b) % p;
}

int add(int a, int b) {
    int s = (a+b);
    if (s>=p) s-=p;
    return s;
}

int sub(int a, int b) {
    int s = (a+p-b);
    if (s>=p) s-=p;
    return s;
}

int po(int a, int deg)
{
    if (deg==0) return 1;
    if (deg%2==1) return mul(a, po(a, deg-1));
    int t = po(a, deg/2);
    return mul(t, t);
}

int inv(int n)
{
    return po(n, p-2);
}

mt19937 rnd(time(0));

/*
const int N = 1200000;

vector<int> facs(N), invfacs(N);

void init()
{
    facs[0] = 1;
    for (int i = 1; i<N; i++) facs[i] = mul(facs[i-1], i);
    invfacs[N-1] = inv(facs[N-1]);
    for (int i = N-2; i>=0; i--) invfacs[i] = mul(invfacs[i+1], i+1);
}

int C(int n, int k)
{
    if (n<k) return 0;
    return mul(facs[n], mul(invfacs[k], invfacs[n-k]));
}
*/

vector<vector<pair<int, int>>> G;

const int N = 200000;

vector<vector<bitset<N>>> dp;
vector<vector<bool>> can;

ll res = 0;

int n, m, k;

void recurse(int cur, bitset<N> bad)
{
    if (cur==k) {res++; return;}
    for (int i = 0; i<dp[cur].size(); i++) if (can[cur][i])
    {
        if ((bad&dp[cur][i]).count()) continue;
        else
        {
            bitset<N> temp = (bad|dp[cur][i]);
            recurse(cur+1, temp);
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(nullptr);
    cin>>n>>m>>k;
    G.resize(n);
    for (int i = 0; i<m; i++)
    {
        int u, v, w;
        cin>>u>>v>>w;
        u--; v--;
        G[u].push_back(mp(w, v));
    }

    for (int i = 0; i<n; i++) sort(G[i].begin(), G[i].end());

    for (int i = 0; i<k; i++)
    {
        dp.push_back(vector<bitset<N>>(i+1));
        can.push_back(vector<bool>(i+1, true));
    }

    for (int i = 0; i<n; i++)
    {
        int deg = G[i].size();
        for (int j = 0; j<deg; j++)
        {
            if (dp[deg-1][j][G[i][j].second] == 1) can[deg-1][j] = false;
            else dp[deg-1][j][G[i][j].second] = 1;
        }
    }

    vector<pair<int, int>> order(k);
    for (int i = 0; i<n; i++) order[G[i].size()-1].first++;
    for (int i = 0; i<k; i++) order[i].second = i;
    sort(order.begin(), order.end());
    reverse(order.begin(), order.end());

    //for (int i = 0; i<n; i++) cout<<i<<": "<<G[i].size()<<endl;

    bitset<N> clean;
    recurse(0, clean);
    cout<<res<<endl;

    vector<vector<bitset<N>>> dp1;
    vector<vector<bool>> can1;

    for (int i = 0; i<k; i++)
    {
        dp1.push_back(dp[order[i].second]);
        can1.push_back(can[order[i].second]);
    }

    dp = dp1; can1 = can;

    /*for (int i = 0; i<k; i++)
    {
        cout<<i<<": "<<endl;
        for (auto it: dp[i]) cout<<it<<endl;
    }*/

}


#include <bits/stdc++.h>

using namespace std;

int cc = 0;

struct edge{
    int v, u, w, num;
    edge() {}
    void init() {
        cin >> v >> u >> w;
        num = cc++;
    }
};

bool cmp(edge a, edge b) {
    return (a.w < b.w);
}

const int N = 2e5 + 7, K = 10;
vector <edge> gout[N], gin[N];
int poss[N];
bool forbid[K][K][K][K];
int ok[K][K];
int has[N][K][K];
pair <int, int> kek[N];
int res = 0;
int cur[K];

void rec(int pos, int k) {
    //cout << pos << ' ' << k << endl;
    if (pos == k + 1) {
        for (int p1 = 1; p1 <= k; p1++) {
            for (int p2 = p1; p2 <= k; p2++) {
                if (forbid[p1][cur[p1]][p2][cur[p2]]) return;
            }
        }
        res++;
        return;
    }
    for (int i = 1; i <= pos; i++) {
        cur[pos] = i;
        rec(pos + 1, k);
        /*if (ok[pos][i] > 0) continue;
        //cout << pos << ' '<< k << ' ' << i << endl;
        if (forbid[pos][i][pos][i]) continue;
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]++;
            }
        }
        rec(pos + 1, k);
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]--;
            }
        }*/
    }
}

signed main() {
    memset(forbid, 0, sizeof(forbid));
    memset(has, 0, sizeof(has));
    //freopen("Desktop/input.txt", "r", stdin);
    ios_base :: sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 0; i < m; i++) {
        edge e;
        e.init();
        gout[e.v].push_back(e);
        gin[e.u].push_back(e);
    }
    for (int i = 1; i <= n; i++) {
        sort(gout[i].begin(), gout[i].end(), cmp);
        for (int j = 0; j < (int) gout[i].size(); j++) {
            kek[gout[i][j].num] = {gout[i].size(), j + 1};
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int a = 0; a < (int) gin[i].size(); a++) {
            auto aa = kek[gin[i][a].num];
            has[i][aa.first][aa.second]++;
        }
        for (int a = 1; a <= k; a++) {
            for (int b = 1; b <= k; b++) {
                for (int v = 1; v <= a; v++) {
                    for (int u = 1; u <= b; u++) {
                        if (has[i][a][v] && has[i][b][u]) {
                            if (a != b || v != u || has[i][a][v] >= 2) forbid[a][v][b][u] = forbid[b][u][a][v] = 1;
                        }
                    }
                }
            }
        }
    }
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= i; j++) {
            ok[i][j] = 0;
        }
    }
    rec(1, k);
    cout << res << endl;
}


#include <bits/stdc++.h>

using namespace std;

int cc = 0;

struct edge{
    int v, u, w, num;
    edge() {}
    void init() {
        cin >> v >> u >> w;
        num = cc++;
    }
};

bool cmp(edge a, edge b) {
    return (a.w < b.w);
}

const int N = 2e5 + 7, K = 10;
vector <edge> gout[N], gin[N];
int poss[N];
bool forbid[K][K][K][K];
int ok[K][K];
int has[N][K][K];
pair <int, int> kek[N];
int res = 0;
int cur[K];

void rec(int pos, int k) {
    //cout << pos << ' ' << k << endl;
    if (pos == k + 1) {
        /*for (int p1 = 1; p1 <= k; p1++) {
            for (int p2 = p1; p2 <= k; p2++) {
                if (forbid[p1][cur[p1]][p2][cur[p2]]) return;
            }
        }*/
        res++;
        return;
    }
    for (int i = 1; i <= pos; i++) {
        cur[pos] = i;
        //rec(pos + 1, k);
        if (ok[pos][i] > 0) continue;
        //cout << pos << ' '<< k << ' ' << i << endl;
        if (forbid[pos][i][pos][i]) continue;
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]++;
            }
        }
        rec(pos + 1, k);
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]--;
            }
        }
    }
}

signed main() {
    memset(forbid, 0, sizeof(forbid));
    memset(has, 0, sizeof(has));
    //freopen("Desktop/input.txt", "r", stdin);
    ios_base :: sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 0; i < m; i++) {
        edge e;
        e.init();
        gout[e.v].push_back(e);
        gin[e.u].push_back(e);
    }
    for (int i = 1; i <= n; i++) {
        sort(gout[i].begin(), gout[i].end(), cmp);
        for (int j = 0; j < (int) gout[i].size(); j++) {
            kek[gout[i][j].num] = {gout[i].size(), j + 1};
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int a = 0; a < (int) gin[i].size(); a++) {
            auto aa = kek[gin[i][a].num];
            has[i][aa.first][aa.second]++;
        }
        for (int a = 1; a <= k; a++) {
            for (int b = 1; b <= k; b++) {
                for (int v = 1; v <= a; v++) {
                    for (int u = 1; u <= b; u++) {
                        if (has[i][a][v] && has[i][b][u]) {
                            if (a != b || v != u || has[i][a][v] >= 2) forbid[a][v][b][u] = forbid[b][u][a][v] = 1;
                        }
                    }
                }
            }
        }
    }
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= i; j++) {
            ok[i][j] = 0;
        }
    }
    rec(1, k);
    cout << res << endl;
}


#include <bits/stdc++.h>

using namespace std;

int cc = 0;

struct edge{
    int v, u, w, num;
    edge() {}
    void init() {
        cin >> v >> u >> w;
        num = cc++;
    }
};

bool cmp(edge a, edge b) {
    return (a.w < b.w);
}

const int N = 2e5 + 7, K = 10;
vector <edge> gout[N], gin[N];
int poss[N];
bool forbid[K][K][K][K];
int ok[K][K];
pair <int, int> kek[N];
int res = 0;

void rec(int pos, int k) {
    //cout << pos << ' ' << k << endl;
    if (pos == k + 1) {
        res++;
        return;
    }
    for (int i = 1; i <= pos; i++) {
        if (ok[pos][i] > 0) continue;
        //cout << pos << ' '<< k << ' ' << i << endl;
        if (forbid[pos][i][pos][i]) continue;
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]++;
            }
        }
        rec(pos + 1, k);
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]--;
            }
        }
    }
}

signed main() {
    memset(forbid, 0, sizeof(forbid));
    //freopen("Desktop/input.txt", "r", stdin);
    ios_base :: sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 0; i < m; i++) {
        edge e;
        e.init();
        gout[e.v].push_back(e);
        gin[e.u].push_back(e);
    }
    for (int i = 1; i <= n; i++) {
        sort(gout[i].begin(), gout[i].end(), cmp);
        for (int j = 0; j < (int) gout[i].size(); j++) {
            kek[gout[i][j].num] = {gout[i].size(), j + 1};
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int a = 0; a < (int) gin[i].size(); a++) {
            for (int b = a + 1; b < (int) gin[i].size(); b++) {
                auto aa = kek[gin[i][a].num], bb = kek[gin[i][b].num];
                forbid[aa.first][aa.second][bb.first][bb.second] = 1;
                forbid[bb.first][bb.second][aa.first][aa.second] = 1;
            }
        }
    }
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= i; j++) {
            ok[i][j] = 0;
        }
    }
    rec(1, k);
    cout << res << endl;
}


#include <bits/stdc++.h>

using namespace std;

int cc = 0;

struct edge{
    int v, u, w, num;
    edge() {}
    void init() {
        cin >> v >> u >> w;
        num = cc++;
    }
};

bool cmp(edge a, edge b) {
    return (a.w < b.w);
}

const int N = 2e5 + 7, K = 10;
vector <edge> gout[N], gin[N];
int poss[N];
bool forbid[K][K][K][K];
int ok[K][K];
pair <int, int> kek[N];
int res = 0;
int cur[K];

void rec(int pos, int k) {
    //cout << pos << ' ' << k << endl;
    if (pos == k + 1) {
        for (int p1 = 1; p1 <= k; p1++) {
            for (int p2 = p1; p2 <= k; p2++) {
                if (forbid[p1][cur[p1]][p2][cur[p2]]) return;
            }
        }
        res++;
        return;
    }
    for (int i = 1; i <= pos; i++) {
        cur[pos] = i;
        rec(pos + 1, k);
        /*if (ok[pos][i] > 0) continue;
        //cout << pos << ' '<< k << ' ' << i << endl;
        if (forbid[pos][i][pos][i]) continue;
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]++;
            }
        }
        rec(pos + 1, k);
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]--;
            }
        }*/
    }
}

signed main() {
    memset(forbid, 0, sizeof(forbid));
    //freopen("Desktop/input.txt", "r", stdin);
    ios_base :: sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 0; i < m; i++) {
        edge e;
        e.init();
        gout[e.v].push_back(e);
        gin[e.u].push_back(e);
    }
    for (int i = 1; i <= n; i++) {
        sort(gout[i].begin(), gout[i].end(), cmp);
        for (int j = 0; j < (int) gout[i].size(); j++) {
            kek[gout[i][j].num] = {gout[i].size(), j + 1};
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int a = 0; a < (int) gin[i].size(); a++) {
            for (int b = a + 1; b < (int) gin[i].size(); b++) {
                auto aa = kek[gin[i][a].num], bb = kek[gin[i][b].num];
                forbid[aa.first][aa.second][bb.first][bb.second] = 1;
                forbid[bb.first][bb.second][aa.first][aa.second] = 1;
            }
        }
    }
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= i; j++) {
            ok[i][j] = 0;
        }
    }
    rec(1, k);
    cout << res << endl;
}


#include <bits/stdc++.h>

using namespace std;

int cc = 0;

struct edge{
    int v, u, w, num;
    edge() {}
    void init() {
        cin >> v >> u >> w;
        num = cc++;
    }
};

bool cmp(edge a, edge b) {
    return (a.w < b.w);
}

const int N = 2e5 + 7, K = 10;
vector <edge> gout[N], gin[N];
int poss[N];
bool forbid[K][K][K][K];
int ok[K][K];
int has[N][K][K];
pair <int, int> kek[N];
int res = 0;
int cur[K];

void rec(int pos, int k) {
    //cout << pos << ' ' << k << endl;
    if (pos == k + 1) {
        /*for (int p1 = 1; p1 <= k; p1++) {
            for (int p2 = p1; p2 <= k; p2++) {
                if (forbid[p1][cur[p1]][p2][cur[p2]]) return;
            }
        }*/
        res++;
        return;
    }
    for (int i = 1; i <= pos; i++) {
        cur[pos] = i;
        rec(pos + 1, k);
        if (ok[pos][i] > 0) continue;
        //cout << pos << ' '<< k << ' ' << i << endl;
        if (forbid[pos][i][pos][i]) continue;
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]++;
            }
        }
        rec(pos + 1, k);
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]--;
            }
        }
    }
}

signed main() {
    memset(forbid, 0, sizeof(forbid));
    memset(has, 0, sizeof(has));
    //freopen("Desktop/input.txt", "r", stdin);
    ios_base :: sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 0; i < m; i++) {
        edge e;
        e.init();
        gout[e.v].push_back(e);
        gin[e.u].push_back(e);
    }
    for (int i = 1; i <= n; i++) {
        sort(gout[i].begin(), gout[i].end(), cmp);
        for (int j = 0; j < (int) gout[i].size(); j++) {
            kek[gout[i][j].num] = {gout[i].size(), j + 1};
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int a = 0; a < (int) gin[i].size(); a++) {
            auto aa = kek[gin[i][a].num];
            has[i][aa.first][aa.second]++;
        }
        for (int a = 1; a <= k; a++) {
            for (int b = 1; b <= k; b++) {
                for (int v = 1; v <= a; v++) {
                    for (int u = 1; u <= b; u++) {
                        if (has[i][a][v] && has[i][b][u]) {
                            if (a != b || v != u || has[i][a][v] >= 2) forbid[a][v][b][u] = forbid[b][u][a][v] = 1;
                        }
                    }
                }
            }
        }
    }
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= i; j++) {
            ok[i][j] = 0;
        }
    }
    rec(1, k);
    cout << res << endl;
}


#include <bits/stdc++.h>

using namespace std;

int cc = 0;

struct edge{
    int v, u, w, num;
    edge() {}
    void init() {
        cin >> v >> u >> w;
        num = cc++;
    }
};

bool cmp(edge a, edge b) {
    return (a.w < b.w);
}

const int N = 2e5 + 7, K = 10;
vector <edge> gout[N], gin[N];
int poss[N];
bool forbid[K][K][K][K];
int ok[K][K];
pair <int, int> kek[N];
int res = 0;
int cur[K];

void rec(int pos, int k) {
    //cout << pos << ' ' << k << endl;
    if (pos == k + 1) {
        for (int p1 = 1; p1 <= k; p1++) {
            for (int p2 = p1; p2 <= k; p2++) {
                if (forbid[p1][cur[p1]][p2][cur[p2]]) return;
            }
        }
        res++;
        return;
    }
    for (int i = 1; i <= pos; i++) {
        cur[k] = i;
        rec(pos + 1, k);
        /*if (ok[pos][i] > 0) continue;
        //cout << pos << ' '<< k << ' ' << i << endl;
        if (forbid[pos][i][pos][i]) continue;
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]++;
            }
        }
        rec(pos + 1, k);
        for (int j = pos + 1; j <= k; j++) {
            for (int v = 1; v <= j; v++) {
                if (forbid[pos][i][j][v]) ok[j][v]--;
            }
        }*/
    }
}

signed main() {
    memset(forbid, 0, sizeof(forbid));
    //freopen("Desktop/input.txt", "r", stdin);
    ios_base :: sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 0; i < m; i++) {
        edge e;
        e.init();
        gout[e.v].push_back(e);
        gin[e.u].push_back(e);
    }
    for (int i = 1; i <= n; i++) {
        sort(gout[i].begin(), gout[i].end(), cmp);
        for (int j = 0; j < (int) gout[i].size(); j++) {
            kek[gout[i][j].num] = {gout[i].size(), j + 1};
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int a = 0; a < (int) gin[i].size(); a++) {
            for (int b = a + 1; b < (int) gin[i].size(); b++) {
                auto aa = kek[gin[i][a].num], bb = kek[gin[i][b].num];
                forbid[aa.first][aa.second][bb.first][bb.second] = 1;
                forbid[bb.first][bb.second][aa.first][aa.second] = 1;
            }
        }
    }
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= i; j++) {
            ok[i][j] = 0;
        }
    }
    rec(1, k);
    cout << res << endl;
}


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

const int N = 2e5;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;

int vis[N], vid;

int cal() {
    int y;
	vid++;
	if(n<800) {
		for(int u=0;u<n;u++) {
			int d = G[u].size();
			y = G[u][c[d-1]].second;
			if(vis[y]==vid) return false;
			vis[y] = vid;
		}
	}else {
		for(int t=0;t<800;t++) {
			int u = rand() % n;
			int d = G[u].size();
			y = G[u][c[d-1]].second;
			if(vis[y]==vid) return false;
			vis[y] = vid;
		}
	}

    return true;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

int main() {
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;

const int N = 2e5;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;
ll S[10][10];
ll ok = 1;

const ll P = 10000000000037ll;

int cal() {
    ll tmp=1;
    for(int i=1;i<=k;i++) tmp = tmp * S[i][c[i-1]] % P;
    return tmp == ok;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

int main() {
    for(int i=0;i<10;i++) {
        for(int j=0;j<10;j++) S[i][j] = 1;
    }

    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)  {
        ok = ok * i % P;
    }

    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        G[u].emplace_back(w,v);
    }
    for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end());

    for(int i=1;i<=n;i++) {
        int d = G[i].size();
        for(int j=0;j<d;j++) {
            S[d][j] = S[d][j] * G[i][j].second % P;
        }
    }

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;

const int N = 2e5+10;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;
ll S[10][10];
ll ok = 1;

const ll P = 10000000000037ll;

int cal() {
    ll tmp=1;
    for(int i=1;i<=k;i++) tmp = tmp * S[i][c[i-1]] % P;
    return tmp == ok;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

bool isprime[4000000];
vector<int> prime;

int main() {
    for(int i=0;i<10;i++) {
        for(int j=0;j<10;j++) S[i][j] = 1;
    }

    memset(isprime,true,sizeof(isprime));

    isprime[0] = isprime[1] = false;

    scanf("%d%d%d",&n,&m,&k);

    for(int i=2;i<4000000; i++) {
        if(isprime[i]) {
            prime.push_back(i);
            ok = ok*i % P;
            if(prime.size()==n) break;
            for(int j=2*i; j<4000000; j+=i) {
                isprime[j] = false;
            }
        }
    }

    // cout<<prime.size()<<endl; return 0;

    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    for(int i=0;i<n;i++) {
        int d = G[i].size();
        for(int j=0;j<d;j++) {
            S[d][j] = S[d][j] * prime[ G[i][j].second ] % P;
        }
    }

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;

const int N = 2e5+10;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;
ll S[10][10];
ll ok = 1;

const ll P = 10000000000037ll;

int cal() {
    ll tmp=1;
    for(int i=0;i<=k;i++) tmp = tmp * S[i][c[i-1]] % P;
    return tmp == ok;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

bool isprime[2000000];
vector<int> prime;

int main() {
    for(int i=0;i<10;i++) {
        for(int j=0;j<10;j++) S[i][j] = 1;
    }

    memset(isprime,true,sizeof(isprime));

    isprime[0] = isprime[1] = false;

    scanf("%d%d%d",&n,&m,&k);

    for(int i=2;i<2000000; i++) {
        if(isprime[i]) {
            prime.push_back(i);
            ok = ok*i % P;
            if(prime.size()==n) break;
        }
        for(int j=2*i; j<2000000; j+=i) {
            isprime[j] = false;
        }
    }

    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    for(int i=0;i<n;i++) {
        int d = G[i].size();
        for(int j=0;j<d;j++) {
            S[d][j] = S[d][j] * prime[ G[i][j].second ] % P;
        }
    }

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;

const int N = 2e5+10;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;
ll S[10][10];
ll ok = 1;

const ll P = 1000000000039ll;

int cal() {
    ll tmp=1;
    for(int i=1;i<=k;i++) tmp = tmp * S[i][c[i-1]] % P;
    return tmp == ok;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

bool isprime[4000000];
vector<int> prime;

int main() {
    for(int i=0;i<10;i++) {
        for(int j=0;j<10;j++) S[i][j] = 1;
    }

    memset(isprime,true,sizeof(isprime));

    isprime[0] = isprime[1] = false;

    scanf("%d%d%d",&n,&m,&k);

    for(int i=2;i<4000000; i++) {
        if(isprime[i]) {
            prime.push_back(i);
            ok = ok*i % P;
            if(prime.size()==n) break;
            for(int j=2*i; j<4000000; j+=i) {
                isprime[j] = false;
            }
        }
    }

    // cout<<prime.size()<<endl; return 0;

    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    for(int i=0;i<n;i++) {
        int d = G[i].size();
        for(int j=0;j<d;j++) {
            S[d][j] = S[d][j] * prime[ G[i][j].second ] % P;
        }
    }

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


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

const int N = 2e5;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;

int vis[N], vid;

int cal() {
    int y;
	vid++;
	if(n<3400) {
		for(int u=0;u<n;u++) {
			int d = G[u].size();
			y = G[u][c[d-1]].second;
			if(vis[y]==vid) return false;
			vis[y] = vid;
		}
	}else {
		for(int t=0;t<3400;t++) {
			int u = rand() % n;
			int d = G[u].size();
			y = G[u][c[d-1]].second;
			if(vis[y]==vid) return false;
			vis[y] = vid;
		}
	}

    return true;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

int main() {
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;

const int N = 2e5+10;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;
ll S[10][10];
ll ok = 1;

const ll P = 1000000000039ll;

int cal() {
    ll tmp=1;
    for(int i=1;i<=k;i++) tmp = tmp * S[i][c[i-1]] % P;
    return tmp == ok;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

bool isprime[4000000];
vector<int> prime;

int main() {
    for(int i=0;i<10;i++) {
        for(int j=0;j<10;j++) S[i][j] = 1;
    }

    memset(isprime,true,sizeof(isprime));

    isprime[0] = isprime[1] = false;

    scanf("%d%d%d",&n,&m,&k);

    for(int i=2;i<4000000; i++) {
        if(isprime[i]) {
            prime.push_back(i);
            ok = ok*i % P;
            if(prime.size()==n) break;
            for(int j=2*i; j<4000000; j+=i) {
                isprime[j] = false;
            }
        }
    }

    cout<<prime.size()<<endl; return 0;

    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    for(int i=0;i<n;i++) {
        int d = G[i].size();
        for(int j=0;j<d;j++) {
            S[d][j] = S[d][j] * prime[ G[i][j].second ] % P;
        }
    }

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;

const int N = 2e5+10;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;
ll S[10][10];
ll ok = 1;

const ll P = 1e9+9;

int cal() {
    ll tmp=1;
    for(int i=1;i<=k;i++) tmp = tmp * S[i][c[i-1]] % P;
    return tmp == ok;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

bool isprime[4000000];
vector<int> prime;

int main() {
    for(int i=0;i<10;i++) {
        for(int j=0;j<10;j++) S[i][j] = 1;
    }

    memset(isprime,true,sizeof(isprime));

    isprime[0] = isprime[1] = false;

    scanf("%d%d%d",&n,&m,&k);

    for(int i=2;i<4000000; i++) {
        if(isprime[i]) {
            prime.push_back(i);
            ok = ok*i % P;
            if(prime.size()==n) break;
            for(int j=2*i; j<4000000; j+=i) {
                isprime[j] = false;
            }
        }
    }

    // cout<<prime.size()<<endl; return 0;

    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    for(int i=0;i<n;i++) {
        int d = G[i].size();
        for(int j=0;j<d;j++) {
            S[d][j] = S[d][j] * prime[ G[i][j].second ] % P;
        }
    }

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;

const int N = 2e5+10;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;
ll S[10][10];
ll ok = 1;

const ll P = 10000000019ll;

int cal() {
    ll tmp=1;
    for(int i=1;i<=k;i++) tmp = tmp * S[i][c[i-1]] % P;
    return tmp == ok;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

bool isprime[4000000];
vector<int> prime;

int main() {
    for(int i=0;i<10;i++) {
        for(int j=0;j<10;j++) S[i][j] = 1;
    }

    memset(isprime,true,sizeof(isprime));

    isprime[0] = isprime[1] = false;

    scanf("%d%d%d",&n,&m,&k);

    for(int i=2;i<4000000; i++) {
        if(isprime[i]) {
            prime.push_back(i);
            ok = ok*i % P;
            if(prime.size()==n) break;
            for(int j=2*i; j<4000000; j+=i) {
                isprime[j] = false;
            }
        }
    }

    // cout<<prime.size()<<endl; return 0;

    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    for(int i=0;i<n;i++) {
        int d = G[i].size();
        for(int j=0;j<d;j++) {
            S[d][j] = S[d][j] * prime[ G[i][j].second ] % P;
        }
    }

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;

const int N = 2e5+10;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;
ll S[10][10];
ll ok = 1;

const ll P = 10000000000037ll;

int cal() {
    ll tmp=1;
    for(int i=1;i<=k;i++) tmp = tmp * S[i][c[i-1]] % P;
    return tmp == ok;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

bool isprime[4000000];
vector<int> prime;

int main() {
    for(int i=0;i<10;i++) {
        for(int j=0;j<10;j++) S[i][j] = 1;
    }

    memset(isprime,true,sizeof(isprime));

    isprime[0] = isprime[1] = false;

    scanf("%d%d%d",&n,&m,&k);

    for(int i=2;i<4000000; i++) {
        if(isprime[i]) {
            prime.push_back(i);
            ok = ok*i % P;
            if(prime.size()==n) break;
        }
        for(int j=2*i; j<4000000; j+=i) {
            isprime[j] = false;
        }
    }

    // cout<<prime.size()<<endl; return 0;

    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    for(int i=0;i<n;i++) {
        int d = G[i].size();
        for(int j=0;j<d;j++) {
            S[d][j] = S[d][j] * prime[ G[i][j].second ] % P;
        }
    }

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;

const int N = 2e5+10;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;
ll S[10][10];
ll ok = 1;

const ll P = 100000000000000003ll;

int cal() {
    ll tmp=0;
    for(int i=1;i<=k;i++) tmp = (tmp + S[i][c[i-1]]) % P;
    return tmp == ok;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

ll h[N];

int main() {

    scanf("%d%d%d",&n,&m,&k);

    h[0] = 1;
    ok = 1;
    for(int i=1;i<n;i++) {
        h[i] = h[i-1] * 2 % P;
        ok = (ok+h[i]) % P;
    }

    // cout<<prime.size()<<endl; return 0;

    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    for(int i=0;i<n;i++) {
        int d = G[i].size();
        for(int j=0;j<d;j++) {
            S[d][j] = (S[d][j] + h[G[i][j].second] )% P;
        }
    }

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;

const int N = 2e5+10;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;
ll S[10][10];
ll ok = 1;

const ll P = 10000000000037ll;

int cal() {
    ll tmp=1;
    for(int i=0;i<=k;i++) tmp = tmp * S[i][c[i-1]] % P;
    return tmp == ok;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

bool isprime[4000000];
vector<int> prime;

int main() {
    for(int i=0;i<10;i++) {
        for(int j=0;j<10;j++) S[i][j] = 1;
    }

    memset(isprime,true,sizeof(isprime));

    isprime[0] = isprime[1] = false;

    scanf("%d%d%d",&n,&m,&k);

    for(int i=2;i<4000000; i++) {
        if(isprime[i]) {
            prime.push_back(i);
            ok = ok*i % P;
            if(prime.size()==n) break;
        }
        for(int j=2*i; j<4000000; j+=i) {
            isprime[j] = false;
        }
    }

    // cout<<prime.size()<<endl; return 0;

    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    for(int i=0;i<n;i++) {
        int d = G[i].size();
        for(int j=0;j<d;j++) {
            S[d][j] = S[d][j] * prime[ G[i][j].second ] % P;
        }
    }

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


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

const int N = 2e5;
vector <pair<int,int> > G[N];
int n,m,k;
int c[10];
int ans;

int vis[N], vid;

int cal() {
    int y;
	vid++;
	if(n<2048) {
		for(int u=0;u<n;u++) {
			int d = G[u].size();
			y = G[u][c[d-1]].second;
			if(vis[y]==vid) return false;
			vis[y] = vid;
		}
	}else {
		for(int t=0;t<2048;t++) {
			int u = rand() % n;
			int d = G[u].size();
			y = G[u][c[d-1]].second;
			if(vis[y]==vid) return false;
			vis[y] = vid;
		}
	}

    return true;
}

void dfs(int d) {
    if(d==k) {
        if(cal()) {
            ans++;
        }
        return;
    }
    for(int i=0;i<=d;i++) c[d] = i, dfs(d+1);
}

int main() {
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<m;i++) {
        int u,v,w;
        scanf("%d%d%d", &u, &v, &w);
        u--, v--;
        G[u].emplace_back(w,v);
    }
    for(int i=0;i<n;i++) sort(G[i].begin(),G[i].end());

    dfs(0);
    cout<<ans<<endl;
    return 0;
}


#include "bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace std;
using namespace __gnu_pbds;

#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 read(x) for (int xx = 0; xx < sz(x); ++xx) cin >> x[xx];

template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
using ll = long long;

using ii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vii = vector<ii>;
using vvii = vector<vii>;

mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count());

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

// xz

int n, k, N;

const int mxn = 2e5, mxk = 10, mxN = mxk * mxk;
int S[mxn][mxN];
int E[mxN][mxN];
int sz[mxN];
int vis[mxN];

int F[mxn][mxk];
int W[mxn][mxk];
int deg[mxn];

int id(int d, int i) { return d * k + i; }

int dfs(int i)
{
    if (i == k) return 1;

    int ct = 0;
    for (auto z = 0; z <= i; ++z)
    {
        int x = id(i, z);
        if (vis[x]) continue;
        for (auto y : E[x])
        {
            if (y == -1) break;
            vis[y]++;
        }
        ct += dfs(i + 1);
        for (auto y : E[x])
        {
            if (y == -1) break;
            vis[y]--;
        }
    }
    return ct;
}

int main()
{ _
    int m; cin >> n >> m >> k; N = k * k;

    memset(S, 0, sizeof(S));
    memset(E, -1, sizeof(E));
    memset(sz, 0, sizeof(sz));
    memset(vis, 0, sizeof(vis));

    memset(F, -1, sizeof(F));
    memset(W, 0, sizeof(W));
    memset(deg, 0, sizeof(deg));

    for (int j = 0; j < m; ++j)
    {
        int u, v, w; cin >> u >> v >> w; --u, --v;
        F[u][deg[u]] = v;
        W[u][deg[u]] = w;
        ++deg[u];
    }

    int temp[mxn] = { 0 };
    for (int u = 0; u < n; ++u)
    {
        for (int i = 0; i < deg[u]; ++i)
            temp[F[u][i]] = W[u][i];
        sort(F[u], F[u] + deg[u], [&](int x, int y) { return temp[x] < temp[y]; });
        for (int i = 0; i < deg[u];++i)
            S[F[u][i]][id(deg[u] - 1, i)] += 1;
    }

    for (int v = 0; v < n; ++v)
        for (int x = 0; x < N; ++x)
        {
            if (S[v][x] > 1) vis[x]++;
            for (int y = x + 1; y < N; ++y)
                if (S[v][x] && S[v][y]) E[x][sz[x]++] = y;
        }

    int ans = dfs(0);

    cout << ans << endl;

    exit(0);
}


#include "bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace std;
using namespace __gnu_pbds;

#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()

template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
using ll = long long;

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

// xz

int main()
{ _
    int n, m, k; cin >> n >> m >> k;

    vector F(n, vector(0, pair(0, 0)));
    for (int j = 0; j < m; ++j)
    {
        int u, v, w; cin >> u >> v >> w; --u, --v;
        F[u].push_back(pair(w, v));
    }

    vector d(n, 0);
    for (int u = 0; u < n; ++u)
    {
        d[u] = sz(F[u]);
        sort(all(F[u]));
        int ct = 0;
        for (auto& [w, v] : F[u])
            w = ct++;
    }

    auto id = [&k](int d, int i) { return d * k + i; };

    vector S(n, vector(k * k, 0));
    for (int u = 0; u < n; ++u)
        for (auto [w, v] : F[u])
            S[v][id(d[u] - 1, w)] += 1;

    vector A(k * k, vector(k * k, 0));
    for (int v = 0; v < n; ++v)
        for (int x = 0; x < k * k; ++x)
        {
            A[x][x] = A[x][x] || S[v][x] > 1;
            for (int y = 0; y < x; ++y)
                A[x][y] = A[y][x] = A[x][y] || A[y][x] || (S[v][x] && S[v][y]);
        }

    vector c(k, 0);

    function<int(int)> dfs = [&](int x)
    {
        if (x == k) return 1;

        int ct = 0;
        for (int i = 0; i <= x; ++i)
        {
            bool bad = false;
            c[x] = i;

            for (int y = 0; y <= x; ++y)
                if (A[id(x, c[x])][id(y, c[y])]) bad = true;
            if (bad) continue;

            ct += dfs(x + 1);
        }
        return ct;
    };

    int ans = dfs(0);

    cout << ans << endl;

    exit(0);
}


#include "bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace std;
using namespace __gnu_pbds;

#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()
#define read(x) for (int xx = 0; xx < sz(x); ++xx) cin >> x[xx];

template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
using ll = long long;

using ii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vii = vector<ii>;
using vvii = vector<vii>;

mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count());

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

// xz

int main()
{ _
    int n, m, k; cin >> n >> m >> k;

    vvii F(n);
    for (int j = 0; j < m; ++j)
    {
        int u, v, w; cin >> u >> v >> w; --u, --v;
        F[u].push_back(pair(w, v));
    }

    vi d(n);
    for (int u = 0; u < n; ++u)
    {
        d[u] = sz(F[u]);
        sort(all(F[u]));
        int ct = 0;
        for (auto& [w, v] : F[u])
            w = ct++;
    }

    int N = k * k;
    vector E(N, vector(0, 0));

    auto id = [&k](int d, int i)
    {
        return d * k + i;
    };

    vvi S(n, vi(k * k, 0));
    for (int u = 0; u < n; ++u)
        for (auto [w, v] : F[u])
            S[v][id(d[u] - 1, w)] += 1;

    vi vis(N, 0);
    for (int v = 0; v < n; ++v)
        for (int x = 0; x < N; ++x)
        {
            if (S[v][x] > 1) vis[x]++;
            for (int y = x + 1; y < N; ++y)
                if (S[v][x] && S[v][y]) E[x].push_back(y);
        }

    function<int(int)> dfs = [&](int i)
    {
        if (i == k) return 1;

        int ct = 0;
        for (auto z = 0; z <= i; ++z)
        {
            int x = id(i, z);
            if (vis[x]) continue;
            for (auto y : E[x]) vis[y]++;
            ct += dfs(i + 1);
            for (auto y : E[x]) vis[y]--;
        }
        return ct;
    };

    int ans = dfs(0);

    cout << ans << endl;

    exit(0);
}


#include "bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace std;
using namespace __gnu_pbds;

#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()
#define read(x) for (int xx = 0; xx < sz(x); ++xx) cin >> x[xx];

template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
using ll = long long;

using ii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vii = vector<ii>;
using vvii = vector<vii>;

mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count());

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

// xz

int main()
{ _
    int n, m, k; cin >> n >> m >> k;

    vvii F(n);
    for (int j = 0; j < m; ++j)
    {
        int u, v, w; cin >> u >> v >> w; --u, --v;
        F[u].push_back(pair(w, v));
    }

    vi d(n);
    for (int u = 0; u < n; ++u)
    {
        d[u] = sz(F[u]);
        sort(all(F[u]));
        int ct = 0;
        for (auto& [w, v] : F[u])
            w = ct++;
    }

    auto id = [&k](int d, int i)
    {
        return d * k + i;
    };

    vvi S(n, vi(k * k, 0));
    for (int u = 0; u < n; ++u)
        for (auto [w, v] : F[u])
            S[v][id(d[u] - 1, w)] += 1;

    vvi A(k * k, vi(k * k, 0));
    for (int v = 0; v < n; ++v)
        for (int x = 0; x < k * k; ++x)
        {
            A[x][x] = A[x][x] || S[v][x] > 1;
            for (int y = 0; y < x; ++y)
                A[x][y] = A[y][x] = A[x][y] || (S[v][x] && S[v][y]);
        }

    vi c(k, 0);
    auto next = [&]()
    {
        c[k - 1] += 1;
        for (int i = k - 1; i > 0; --i)
            if (c[i] > i)
                c[i] = 0, c[i - 1] += 1;
    };

    auto feasible = [&]()
    {
        for (int i = 0; i < k; ++i)
            for (int j = 0; j <= i; ++j)
                if (A[id(i, c[i])][id(j, c[j])])
                    return false;
        return true;
    };

    int MAX = 1;
    for (int i = 1; i <= k; ++i) MAX *= i;

    int ans = 0;
    while (MAX--)
    {
        ans += feasible();
        next();
    }

    cout << ans << endl;

    exit(0);
}


#include "bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace std;
using namespace __gnu_pbds;

#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 read(x) for (int xx = 0; xx < sz(x); ++xx) cin >> x[xx];

template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
using ll = long long;

using ii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vii = vector<ii>;
using vvii = vector<vii>;

mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count());

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

// xz

int n, k, N;

const int mxn = 2e5, mxk = 10, maxN = mxk * mxk;
int S[mxn][mxk][mxk];
int E[mxk][mxk];
int sz[mxk];
int vis[maxN];

int id(int d, int i) { return d * k + i; }

int dfs(int i)
{
    if (i == k) return 1;

    int ct = 0;
    for (auto z = 0; z <= i; ++z)
    {
        int x = id(i, z);
        if (vis[x]) continue;
        for (auto y : E[x])
        {
            if (y == -1) break;
            vis[y]++;
        }
        ct += dfs(i + 1);
        for (auto y : E[x]) vis[y]--;
    }
    return ct;
}

int main()
{ _
    int n, m, k; cin >> n >> m >> k; N = k * k;

    memset(S, -1, sizeof(S));
    memset(E, -1, sizeof(E));
    memset(sz, 0, sizeof(sz));
    memset(vis, 0, sizeof(vis));

    vvii F(n);
    for (int j = 0; j < m; ++j)
    {
        int u, v, w; cin >> u >> v >> w; --u, --v;
        F[u].push_back(pair(w, v));
    }

    vi d(n);
    for (int u = 0; u < n; ++u)
    {
        d[u] = (int)F[u].size();
        sort(all(F[u]));
        int ct = 0;
        for (auto& [w, v] : F[u])
            w = ct++;
    }

    vvi S(n, vi(k * k, 0));
    for (int u = 0; u < n; ++u)
        for (auto [w, v] : F[u])
            S[v][id(d[u] - 1, w)] += 1;

    vi vis(N, 0);
    for (int v = 0; v < n; ++v)
        for (int x = 0; x < N; ++x)
        {
            if (S[v][x] > 1) vis[x]++;
            for (int y = x + 1; y < N; ++y)
                if (S[v][x] && S[v][y]) E[x][sz[x]++] = y;
        }

    int ans = dfs(0);

    cout << ans << endl;

    exit(0);
}


#include "bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace std;
using namespace __gnu_pbds;

#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 read(x) for (int xx = 0; xx < sz(x); ++xx) cin >> x[xx];

template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
using ll = long long;

mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count());

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

// xz

int n, k, N;

const int mxn = 2e5, mxk = 10, mxN = mxk * mxk;

ll S[mxk][mxk];
ll val[mxn];
ll good;

int F[mxn][mxk];
int W[mxn][mxk];
int deg[mxn];

int id(int d, int i) { return d * k + i; }

int dfs(int i, ll sum)
{
    if (i == k) return sum == good;

    int ct = 0;
    for (auto z = 0; z <= i; ++z)
        ct += dfs(i + 1, sum + S[i][z]);

    return ct;
}

int main()
{ _
    int m; cin >> n >> m >> k; N = k * k;

    memset(S, 0, sizeof(S));

    memset(F, -1, sizeof(F));
    memset(W, 0, sizeof(W));
    memset(deg, 0, sizeof(deg));

    for (int j = 0; j < m; ++j)
    {
        int u, v, w; cin >> u >> v >> w; --u, --v;
        F[u][deg[u]] = v;
        W[u][deg[u]] = w;
        ++deg[u];
    }

    uniform_int_distribution<ll> unif(1e8, 1e9);
    for (int u = 0; u < n; ++u) val[u] = unif(rng);
    good = accumulate(val, val + n, 0LL);

    int temp[mxn] = { 0 };
    for (int u = 0; u < n; ++u)
    {
        for (int i = 0; i < deg[u]; ++i)
            temp[F[u][i]] = W[u][i];
        sort(F[u], F[u] + deg[u], [&](int x, int y) { return temp[x] < temp[y]; });
        for (int i = 0; i < deg[u];++i)
            S[deg[u] - 1][i] += val[F[u][i]];
    }

    int ans = dfs(0, 0LL);

    cout << ans << endl;

    exit(0);
}


#include "bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace std;
using namespace __gnu_pbds;

#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 read(x) for (int xx = 0; xx < sz(x); ++xx) cin >> x[xx];

template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
using ll = long long;

using ii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vii = vector<ii>;
using vvii = vector<vii>;

mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count());

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

// xz

int n, k, N;

const int mxn = 2e5, mxk = 10, mxN = mxk * mxk;
int S[mxn][mxN];
int E[mxN][mxN];
int sz[mxN];
int vis[mxN];

int id(int d, int i) { return d * k + i; }

int dfs(int i)
{
    if (i == k) return 1;

    int ct = 0;
    for (auto z = 0; z <= i; ++z)
    {
        int x = id(i, z);
        if (vis[x]) continue;
        for (auto y : E[x])
        {
            if (y == -1) break;
            vis[y]++;
        }
        ct += dfs(i + 1);
        for (auto y : E[x])
        {
            if (y == -1) break;
            vis[y]--;
        }
    }
    return ct;
}

int main()
{ _
    int m; cin >> n >> m >> k; N = k * k;

    memset(S, 0, sizeof(S));
    memset(E, -1, sizeof(E));
    memset(sz, 0, sizeof(sz));
    memset(vis, 0, sizeof(vis));

    vvii F(n);
    for (int j = 0; j < m; ++j)
    {
        int u, v, w; cin >> u >> v >> w; --u, --v;
        F[u].push_back(pair(w, v));
    }

    vi d(n);
    for (int u = 0; u < n; ++u)
    {
        d[u] = (int)F[u].size();
        sort(all(F[u]));
        int ct = 0;
        for (auto& [w, v] : F[u])
            w = ct++;
    }

    for (int u = 0; u < n; ++u)
        for (auto [w, v] : F[u])
            S[v][id(d[u] - 1, w)] += 1;

    for (int v = 0; v < n; ++v)
        for (int x = 0; x < N; ++x)
        {
            if (S[v][x] > 1) vis[x]++;
            for (int y = x + 1; y < N; ++y)
                if (S[v][x] && S[v][y]) E[x][sz[x]++] = y;
        }

    int ans = dfs(0);

    cout << ans << endl;

    exit(0);
}


#include "bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace std;
using namespace __gnu_pbds;

#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()
#define read(x) for (int xx = 0; xx < sz(x); ++xx) cin >> x[xx];

template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
using ll = long long;

using ii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vii = vector<ii>;
using vvii = vector<vii>;

mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count());

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

// xz

int dfs(const vvi& E, vi& vis, int i, int k)
{
    if (i == k) return 1;

    int ct = 0;
    for (auto z = 0; z <= i; ++z)
    {
        int x = i * k + z;
        if (vis[x]) continue;
        for (auto y : E[x]) vis[y]++;
        ct += dfs(E, vis, i + 1, k);
        for (auto y : E[x]) vis[y]--;
    }
    return ct;
}

int main()
{ _
    int n, m, k; cin >> n >> m >> k;

    vvii F(n);
    for (int j = 0; j < m; ++j)
    {
        int u, v, w; cin >> u >> v >> w; --u, --v;
        F[u].push_back(pair(w, v));
    }

    vi d(n);
    for (int u = 0; u < n; ++u)
    {
        d[u] = sz(F[u]);
        sort(all(F[u]));
        int ct = 0;
        for (auto& [w, v] : F[u])
            w = ct++;
    }

    int N = k * k;
    vector E(N, vector(0, 0));

    auto id = [&k](int d, int i)
    {
        return d * k + i;
    };

    vvi S(n, vi(k * k, 0));
    for (int u = 0; u < n; ++u)
        for (auto [w, v] : F[u])
            S[v][id(d[u] - 1, w)] += 1;

    vi vis(N, 0);
    for (int v = 0; v < n; ++v)
        for (int x = 0; x < N; ++x)
        {
            if (S[v][x] > 1) vis[x]++;
            for (int y = x + 1; y < N; ++y)
                if (S[v][x] && S[v][y]) E[x].push_back(y);
        }

    int ans = dfs(E, vis, 0, k);

    cout << ans << endl;

    exit(0);
}