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

#define ll long long
#define ar array

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

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

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

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

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


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

#define ll long long
#define ar array

int n, m, k;
vector<pair<int, int>> temp[200000];
vector<int> adj[200000];
vector<vector<int>> v[10];
vector<bitset<200000>> b[10];

bool vis[200000];
int ans=0;
void rec(bitset<200000> cur, int x=1, int sum=0) {
	if (x==k+1) {
		++ans;
		return;
	}
	sum+=v[x].size();
	for (int i=0; i<x; ++i) {
		bitset<200000> nxt=cur|b[x][i];
		if (nxt.count()!=sum) continue;
		rec(nxt, x+1, sum);
		/*vector<int> rb;
		bool chk=1;
		for (auto t: v[x]) {
			int k=t[i];
			if (vis[k]) {
				chk=0;
				break;
			}
			vis[k]=1;
			rb.push_back(k);
		}
		if (chk) {
			rec(x+1);
		}
		for (int i: rb)
			vis[i]=0;*/
	}
}

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

	cin >> n >> m >> k;
	for (int i=0; i<m; ++i) {
		int a, b, w; cin >> a >> b >> w, --a, --b;
		temp[a].emplace_back(w, b);
	}
	for (int i=0; i<n; ++i) {
		sort(temp[i].begin(), temp[i].end());
		for (auto x: temp[i])
			adj[i].push_back(x.second);
		assert(1<=adj[i].size()&&adj[i].size()<=k);
		v[adj[i].size()].push_back(adj[i]);
	}
	for (int i=1; i<=k; ++i) {
		for (int j=0; j<i; ++j) {
			bitset<200000> cur;
			for (auto x: v[i])
				cur[x[j]]=1;
			b[i].push_back(cur);
		}
	}
	bitset<200000> orig;
	rec(orig);
	cout << ans;
	return 0;
}

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


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

#define ll long long
#define ar array

int n, m, k;
vector<pair<int, int>> temp[200000];
vector<int> adj[200000];
vector<vector<int>> v[10];
vector<int> perm;
//map<pair<int, int>, int> oc[200000];

bool vis[200000];
int ans=0;

void rec(int step=0) {
	if (step==k) {
		++ans;
		return;
	}
	int x=perm[step];
	for (int i=0; i<x; ++i) {
		vector<int> rb;
		bool chk=1;
		for (auto t: v[x]) {
			int k=t[i];
			if (vis[k]) {
				chk=0;
				break;
			}
			vis[k]=1;
			rb.push_back(k);
		}
		if (chk) {
			rec(step+1);
		}
		for (int i: rb)
			vis[i]=0;
	}
}

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

	cin >> n >> m >> k;
	for (int i=0; i<m; ++i) {
		int a, b, w; cin >> a >> b >> w, --a, --b;
		temp[a].emplace_back(w, b);
	}
	for (int i=0; i<n; ++i) {
		sort(temp[i].begin(), temp[i].end());
		for (auto x: temp[i])
			adj[i].push_back(x.second);
		assert(1<=adj[i].size()&&adj[i].size()<=k);
		v[adj[i].size()].push_back(adj[i]);
		//for (int j=0; j<adj[i].size(); ++j)
		//	oc[adj[i][j]][{adj[i].size(), j}]++;
	}
	perm.resize(k); iota(perm.begin(), perm.end(), 1);
	sort(perm.begin(), perm.end(), [](int a, int b) {return v[a].size()>v[b].size();});
	/*for (int i=0; i<n; ++i) {
		cout << "\n\n";
		for (auto x: oc[i])
			cout << x.first.first << ' ' << x.first.second << ' ' << x.second << '\n';
	}*/
	rec();
	cout << ans;
	return 0;
}

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


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

#define ll long long
#define ar array

int n, m, k;
vector<pair<int, int>> temp[200000];
vector<int> adj[200000];
vector<vector<int>> v[10];

bool vis[200000];
int ans=0;
void rec(int x=1) {
	if (x==k+1) {
		++ans;
		return;
	}
	for (int i=0; i<x; ++i) {
		vector<int> rb;
		bool chk=1;
		for (auto t: v[x]) {
			int k=t[i];
			if (vis[k]) {
				chk=0;
				break;
			}
			vis[k]=1;
			rb.push_back(k);
		}
		if (chk) {
			rec(x+1);
		}
		for (int i: rb)
			vis[i]=0;
	}
}

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

	cin >> n >> m >> k;
	for (int i=0; i<m; ++i) {
		int a, b, w; cin >> a >> b >> w, --a, --b;
		temp[a].emplace_back(w, b);
	}
	for (int i=0; i<n; ++i) {
		sort(temp[i].begin(), temp[i].end());
		for (auto x: temp[i])
			adj[i].push_back(x.second);
		assert(1<=adj[i].size()&&adj[i].size()<=k);
		v[adj[i].size()].push_back(adj[i]);
	}
	rec();
	cout << ans;
	return 0;
}

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


#include <iostream>
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
using namespace std;
using ll = long long int;
struct DSU{
    vector<int> parent;
    vector<int> sizof;
    int n;
    DSU(int N){
        n=N;
        parent.resize(n);
        sizof.resize(n);
        for(int i=0;i<n;i++){
            parent[i]=i;
            sizof[i]=1;
        }
    }
    int get_size(int x){
        return sizof[find_set(x)];
    }
    int find_set(int v){
        if (v == parent[v])
            return v;
        return parent[v] = find_set(parent[v]);
    }
    void join_sets(int a, int b) {
        //cout<<a<<" "<<b<<"\n";
        a = find_set(a);
        b = find_set(b);
        if (a != b) {
            if (sizof[a] < sizof[b]){
                swap(a, b);
            }
            parent[b] = a;
            sizof[a] += sizof[b];
        }
    }
};
struct Edge{
    int u,v,w,idx;
    int k,c;
    Edge(int u,int v,int w,int idx) : u(u), v(v), w(w), idx(idx) {}
    Edge() {}
    bool operator<(const Edge &e){
        return w<e.w;
    }
};
void solve(){
    int n,m,k;
    cin>>n>>m>>k;
    vector<vector<Edge>> adj(n);
    vector<Edge> edges(m);
    for(int i=0;i<m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        --u;--v;
        adj[u].pb(Edge(u,v,w,i));
    }
    for(int i=0;i<n;i++){
        sort(adj[i].begin(), adj[i].end());
        for(int j=0;j<(int)adj[i].size();j++){
            adj[i][j].k = adj[i].size() - 1;
            adj[i][j].c = j;
            edges[adj[i][j].idx] = adj[i][j];
        }
    }
    DSU sat(11*k + 1);
    vector<bool> selfedge(11*k + 1);
    auto addedge = [&](const Edge &x, const Edge &y){
        //cout<<10*x.k+x.c<<" "<<10*y.k + y.c<<"\n";
        if(sat.find_set(10*x.k + x.c) == sat.find_set(10*y.k + y.c)){
            selfedge[10*y.k + y.c] = 1;
            return;
        }
        sat.join_sets(10*x.k + x.c,10*y.k + y.c);
    };

    auto allowed = [&](const pair<int,int> &x, const pair<int,int> &y){
        if(selfedge[y.first*10 + y.second]) return false;
        return sat.find_set(x.first*10 + x.second)!=sat.find_set(10*y.first + y.second);
    };
    vector<int> rep(n, -1);
    for(const auto &e : edges){
        if(~rep[e.v]){
            addedge(edges[rep[e.v]], e);
        }
        rep[e.v] = e.idx;
    }
    ll ans = 0;
    function<void(vector<int>&)> recurse = [&](vector<int>& curr){
        if((int)curr.size()==k){
            /*for(const auto &x : curr){
                cout<<x<<" ";
            }
            cout<<"\n";
            */
            ++ans;
            return;
        }
        int idx = curr.size();
        for(int i=0;i<=idx;i++){
            bool poss = 1;
            for(int j=0;j<(int)curr.size();j++){
                if(!allowed({j, curr[j]}, {idx, i})){
                    poss = 0;
                }
            }
            if(!poss) continue;
            curr.pb(i);
            recurse(curr);
            curr.pop_back();
        }
    };
    vector<int> use;
    recurse(use);
    cout<<ans<<"\n";
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
}


#include <iostream>
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
using namespace std;
using ll = long long int;
struct DSU{
    vector<int> parent;
    vector<int> sizof;
    int n;
    DSU(int N){
        n=N;
        parent.resize(n);
        sizof.resize(n);
        for(int i=0;i<n;i++){
            parent[i]=i;
            sizof[i]=1;
        }
    }
    int get_size(int x){
        return sizof[find_set(x)];
    }
    int find_set(int v){
        if (v == parent[v])
            return v;
        return parent[v] = find_set(parent[v]);
    }
    void join_sets(int a, int b) {
        //cout<<a<<" "<<b<<"\n";
        a = find_set(a);
        b = find_set(b);
        if (a != b) {
            if (sizof[a] < sizof[b]){
                swap(a, b);
            }
            parent[b] = a;
            sizof[a] += sizof[b];
        }
    }
};
struct Edge{
    int u,v,w,idx;
    int k,c;
    Edge(int u,int v,int w,int idx) : u(u), v(v), w(w), idx(idx) {}
    Edge() {}
    bool operator<(const Edge &e){
        return w<e.w;
    }
};
void solve(){
    int n,m,k;
    cin>>n>>m>>k;
    vector<vector<Edge>> adj(n);
    vector<Edge> edges(m);
    for(int i=0;i<m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        --u;--v;
        adj[u].pb(Edge(u,v,w,i));
    }
    for(int i=0;i<n;i++){
        sort(adj[i].begin(), adj[i].end());
        for(int j=0;j<(int)adj[i].size();j++){
            adj[i][j].k = adj[i].size() - 1;
            adj[i][j].c = j;
            edges[adj[i][j].idx] = adj[i][j];
        }
    }
    vector<bool> selfedge(11*k);
    const int MAXN = 2e5 + 7;
    vector<bitset<MAXN>> sol(11*k);
    vector<vector<bool>> allow(11*k, vector<bool>(11*k, 1));
    auto allowed = [&](const pair<int,int> &x, const pair<int,int> &y){
        if(selfedge[y.first*10 + y.second]) return false;
        return bool(allow[10*x.first + x.second][10*y.first + y.second]);
    };
    for(const auto &e : edges){
        if(sol[10*e.k + e.c][e.v]){
            selfedge[10*e.k + e.c] = 1;
        }
        sol[10*e.k + e.c][e.v] = 1;
    }
    for(int i=0;i<11*k;i++){
        for(const auto &e : edges){
            if(10*e.k + e.c == i) continue;
            if(sol[i][e.v]){
                allow[i][10*e.k + e.c] = 0;
                allow[10*e.k + e.c][i] = 0;
            }
        }
    }
    ll ans = 0;
    function<void(vector<int>&)> recurse = [&](vector<int>& curr){
        if((int)curr.size()==k){
            for(const auto &x : curr){
                cout<<x<<" ";
            }
            cout<<"\n";
            ++ans;
            return;
        }
        int idx = curr.size();
        for(int i=0;i<=idx;i++){
            bool poss = 1;
            if(selfedge[10*idx + i]) continue;
            for(int j=0;j<(int)curr.size();j++){
                if(!allowed({j, curr[j]}, {idx, i})){
                    poss = 0;
                }
            }
            if(!poss) continue;
            curr.pb(i);
            recurse(curr);
            curr.pop_back();
        }
    };
    vector<int> use;
    recurse(use);
    cout<<ans<<"\n";
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
}


#include <iostream>
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
using namespace std;
using ll = long long int;
struct DSU{
    vector<int> parent;
    vector<int> sizof;
    int n;
    DSU(int N){
        n=N;
        parent.resize(n);
        sizof.resize(n);
        for(int i=0;i<n;i++){
            parent[i]=i;
            sizof[i]=1;
        }
    }
    int get_size(int x){
        return sizof[find_set(x)];
    }
    int find_set(int v){
        if (v == parent[v])
            return v;
        return parent[v] = find_set(parent[v]);
    }
    void join_sets(int a, int b) {
        //cout<<a<<" "<<b<<"\n";
        a = find_set(a);
        b = find_set(b);
        if (a != b) {
            if (sizof[a] < sizof[b]){
                swap(a, b);
            }
            parent[b] = a;
            sizof[a] += sizof[b];
        }
    }
};
struct Edge{
    int u,v,w,idx;
    int k,c;
    Edge(int u,int v,int w,int idx) : u(u), v(v), w(w), idx(idx) {}
    Edge() {}
    bool operator<(const Edge &e){
        return w<e.w;
    }
};
void solve(){
    int n,m,k;
    cin>>n>>m>>k;
    vector<vector<Edge>> adj(n);
    vector<Edge> edges(m);
    for(int i=0;i<m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        --u;--v;
        adj[u].pb(Edge(u,v,w,i));
    }
    for(int i=0;i<n;i++){
        sort(adj[i].begin(), adj[i].end());
        for(int j=0;j<(int)adj[i].size();j++){
            adj[i][j].k = adj[i].size() - 1;
            adj[i][j].c = j;
            edges[adj[i][j].idx] = adj[i][j];
        }
    }
    vector<bool> selfedge(11*k + 1);
    const int MAXN = 2e5 + 7;
    vector<bitset<MAXN>> sol(11*k);
    vector<vector<bool>> allow(11*k +1, vector<bool>(11*k + 1, 1));
    auto allowed = [&](const pair<int,int> &x, const pair<int,int> &y){
        if(selfedge[y.first*10 + y.second]) return false;
        return bool(allow[10*x.first + x.second][10*y.first + y.second]);
    };
    for(const auto &e : edges){
        if(sol[10*e.k + e.c][e.v]){
            selfedge[10*e.k + e.c] = 1;
        }
        sol[10*e.k + e.c][e.v] = 1;
    }
    for(int i=0;i<11*k;i++){
        for(const auto &e : edges){
            if(10*e.k + e.c == i) continue;
            if(sol[i][e.v]){
                allow[i][10*e.k + e.c] = 0;
                allow[10*e.k + e.c][i] = 0;
            }
        }
    }
    ll ans = 0;
    function<void(vector<int>&)> recurse = [&](vector<int>& curr){
        if((int)curr.size()==k){
            /*for(const auto &x : curr){
                cout<<x<<" ";
            }
            cout<<"\n";
            */
            ++ans;
            return;
        }
        int idx = curr.size();
        for(int i=0;i<=idx;i++){
            bool poss = 1;
            for(int j=0;j<(int)curr.size();j++){
                if(!allowed({j, curr[j]}, {idx, i})){
                    poss = 0;
                }
            }
            if(!poss) continue;
            curr.pb(i);
            recurse(curr);
            curr.pop_back();
        }
    };
    vector<int> use;
    recurse(use);
    cout<<ans<<"\n";
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
}


#include <iostream>
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
using namespace std;
using ll = long long int;
struct DSU{
    vector<int> parent;
    vector<int> sizof;
    int n;
    DSU(int N){
        n=N;
        parent.resize(n);
        sizof.resize(n);
        for(int i=0;i<n;i++){
            parent[i]=i;
            sizof[i]=1;
        }
    }
    int get_size(int x){
        return sizof[find_set(x)];
    }
    int find_set(int v){
        if (v == parent[v])
            return v;
        return parent[v] = find_set(parent[v]);
    }
    void join_sets(int a, int b) {
        //cout<<a<<" "<<b<<"\n";
        a = find_set(a);
        b = find_set(b);
        if (a != b) {
            if (sizof[a] < sizof[b]){
                swap(a, b);
            }
            parent[b] = a;
            sizof[a] += sizof[b];
        }
    }
};
struct Edge{
    int u,v,w,idx;
    int k,c;
    Edge(int u,int v,int w,int idx) : u(u), v(v), w(w), idx(idx) {}
    Edge() {}
    bool operator<(const Edge &e){
        return w<e.w;
    }
};
void solve(){
    int n,m,k;
    cin>>n>>m>>k;
    vector<vector<Edge>> adj(n);
    vector<Edge> edges(m);
    for(int i=0;i<m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        --u;--v;
        adj[u].pb(Edge(u,v,w,i));
    }
    for(int i=0;i<n;i++){
        sort(adj[i].begin(), adj[i].end());
        for(int j=0;j<(int)adj[i].size();j++){
            adj[i][j].k = adj[i].size() - 1;
            adj[i][j].c = j;
            edges[adj[i][j].idx] = adj[i][j];
        }
    }
    vector<bool> selfedge(11*k);
    const int MAXN = 2e5 + 7;
    vector<bitset<MAXN>> sol(11*k);
    vector<vector<bool>> allow(11*k, vector<bool>(11*k, 1));
    auto allowed = [&](const pair<int,int> &x, const pair<int,int> &y){
        if(selfedge[y.first*10 + y.second]) return false;
        return bool(allow[10*x.first + x.second][10*y.first + y.second]);
    };
    for(const auto &e : edges){
        if(sol[10*e.k + e.c][e.v]){
            selfedge[10*e.k + e.c] = 1;
        }
        sol[10*e.k + e.c][e.v] = 1;
    }
    for(int i=0;i<11*k;i++){
        for(const auto &e : edges){
            if(10*e.k + e.c == i) continue;
            if(sol[i][e.v]){
                allow[i][10*e.k + e.c] = 0;
                allow[10*e.k + e.c][i] = 0;
            }
        }
    }
    ll ans = 0;
    function<void(vector<int>&)> recurse = [&](vector<int>& curr){
        if((int)curr.size()==k){
            /*for(const auto &x : curr){
                cout<<x<<" ";
            }
            cout<<"\n";
            */
            ++ans;
            return;
        }
        int idx = curr.size();
        for(int i=0;i<=idx;i++){
            bool poss = 1;
            if(selfedge[10*idx + i]) continue;
            for(int j=0;j<(int)curr.size();j++){
                if(!allowed({j, curr[j]}, {idx, i})){
                    poss = 0;
                }
            }
            if(!poss) continue;
            curr.pb(i);
            recurse(curr);
            curr.pop_back();
        }
    };
    vector<int> use;
    recurse(use);
    cout<<ans<<"\n";
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
}


#include <iostream>
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
using namespace std;
using ll = long long int;
struct DSU{
    vector<int> parent;
    vector<int> sizof;
    int n;
    DSU(int N){
        n=N;
        parent.resize(n);
        sizof.resize(n);
        for(int i=0;i<n;i++){
            parent[i]=i;
            sizof[i]=1;
        }
    }
    int get_size(int x){
        return sizof[find_set(x)];
    }
    int find_set(int v){
        if (v == parent[v])
            return v;
        return parent[v] = find_set(parent[v]);
    }
    void join_sets(int a, int b) {
        //cout<<a<<" "<<b<<"\n";
        a = find_set(a);
        b = find_set(b);
        if (a != b) {
            if (sizof[a] < sizof[b]){
                swap(a, b);
            }
            parent[b] = a;
            sizof[a] += sizof[b];
        }
    }
};
struct Edge{
    int u,v,w,idx;
    int k,c;
    Edge(int u,int v,int w,int idx) : u(u), v(v), w(w), idx(idx) {}
    Edge() {}
    bool operator<(const Edge &e){
        return w<e.w;
    }
};
void solve(){
    int n,m,k;
    cin>>n>>m>>k;
    vector<vector<Edge>> adj(n);
    vector<Edge> edges(m);
    for(int i=0;i<m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        --u;--v;
        adj[u].pb(Edge(u,v,w,i));
    }
    for(int i=0;i<n;i++){
        sort(adj[i].begin(), adj[i].end());
        for(int j=0;j<(int)adj[i].size();j++){
            adj[i][j].k = adj[i].size() - 1;
            adj[i][j].c = j;
            edges[adj[i][j].idx] = adj[i][j];
        }
    }
    DSU sat(11*k);
    vector<bool> selfedge(11*k);
    auto addedge = [&](const Edge &x, const Edge &y){
        if(10*x.k + x.c == 10*y.k + y.c){
            selfedge[10*x.k + x.c] = 1;
        }
        sat.join_sets(10*x.k + x.c,10*y.k + y.c);
    };
    auto allowed = [&](const pair<int,int> &x, const pair<int,int> &y){
        if(selfedge[10*y.first + y.second]) return false;
        return sat.find_set(x.first*10 + x.second)!=sat.find_set(10*y.first + y.second);
    };
    vector<int> rep(n, -1);
    for(const auto &e : edges){
        if(~rep[e.v]){
            addedge(edges[rep[e.v]], e);
        }
        rep[e.v] = e.idx;
    }
    ll ans = 0;
    function<void(vector<int>&)> recurse = [&](vector<int>& curr){
        if((int)curr.size()==k){
            /*for(const auto &x : curr){
                cout<<x<<" ";
            }
            cout<<"\n";
            */
            ++ans;
            return;
        }
        int idx = curr.size();
        for(int i=0;i<=idx;i++){
            bool poss = 1;
            for(int j=0;j<(int)curr.size();j++){
                if(!allowed({j, curr[j]}, {idx, i})){
                    poss = 0;
                }
            }
            if(!poss) continue;
            curr.pb(i);
            recurse(curr);
            curr.pop_back();
        }
    };
    vector<int> use;
    recurse(use);
    cout<<ans<<"\n";
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
}


#include <iostream>
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
using namespace std;
using ll = long long int;
struct DSU{
    vector<int> parent;
    vector<int> sizof;
    int n;
    DSU(int N){
        n=N;
        parent.resize(n);
        sizof.resize(n);
        for(int i=0;i<n;i++){
            parent[i]=i;
            sizof[i]=1;
        }
    }
    int get_size(int x){
        return sizof[find_set(x)];
    }
    int find_set(int v){
        if (v == parent[v])
            return v;
        return parent[v] = find_set(parent[v]);
    }
    void join_sets(int a, int b) {
        //cout<<a<<" "<<b<<"\n";
        a = find_set(a);
        b = find_set(b);
        if (a != b) {
            if (sizof[a] < sizof[b]){
                swap(a, b);
            }
            parent[b] = a;
            sizof[a] += sizof[b];
        }
    }
};
struct Edge{
    int u,v,w,idx;
    int k,c;
    Edge(int u,int v,int w,int idx) : u(u), v(v), w(w), idx(idx) {}
    Edge() {}
    bool operator<(const Edge &e){
        return w<e.w;
    }
};
void solve(){
    int n,m,k;
    cin>>n>>m>>k;
    vector<vector<Edge>> adj(n);
    vector<Edge> edges(m);
    for(int i=0;i<m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        --u;--v;
        adj[u].pb(Edge(u,v,w,i));
    }
    for(int i=0;i<n;i++){
        sort(adj[i].begin(), adj[i].end());
        for(int j=0;j<(int)adj[i].size();j++){
            adj[i][j].k = adj[i].size() - 1;
            adj[i][j].c = j;
            edges[adj[i][j].idx] = adj[i][j];
        }
    }
    DSU sat(11*k + 1);
    vector<bool> selfedge(11*k + 1);
    vector<set<int>> check(n);
    auto addedge = [&](const Edge &x, const Edge &y){
        if(check[y.v].count(10*y.k + y.c)){
            selfedge[10*y.k + y.c] = 1;
            return;
        }
        sat.join_sets(10*x.k + x.c,10*y.k + y.c);
    };
    auto allowed = [&](const pair<int,int> &x, const pair<int,int> &y){
        if(selfedge[y.first*10 + y.second]) return false;
        return sat.find_set(x.first*10 + x.second)!=sat.find_set(10*y.first + y.second);
    };
    vector<int> rep(n, -1);
    for(const auto &e : edges){
        if(~rep[e.v]){
            addedge(edges[rep[e.v]], e);
        }
        rep[e.v] = e.idx;
        check[e.v].insert(10*e.k + e.c);
    }
    ll ans = 0;
    function<void(vector<int>&)> recurse = [&](vector<int>& curr){
        if((int)curr.size()==k){
        /*    for(const auto &x : curr){
                cout<<x<<" ";
            }
            cout<<"\n";
            */
            ++ans;
            return;
        }
        int idx = curr.size();
        for(int i=0;i<=idx;i++){
            bool poss = 1;
            for(int j=0;j<(int)curr.size();j++){
                if(!allowed({j, curr[j]}, {idx, i})){
                    poss = 0;
                }
            }
            if(!poss) continue;
            curr.pb(i);
            recurse(curr);
            curr.pop_back();
        }
    };
    vector<int> use;
    recurse(use);
    cout<<ans<<"\n";
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
}


#include <iostream>
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
using namespace std;
using ll = long long int;
struct DSU{
    vector<int> parent;
    vector<int> sizof;
    int n;
    DSU(int N){
        n=N;
        parent.resize(n);
        sizof.resize(n);
        for(int i=0;i<n;i++){
            parent[i]=i;
            sizof[i]=1;
        }
    }
    int get_size(int x){
        return sizof[find_set(x)];
    }
    int find_set(int v){
        if (v == parent[v])
            return v;
        return parent[v] = find_set(parent[v]);
    }
    void join_sets(int a, int b) {
        //cout<<a<<" "<<b<<"\n";
        a = find_set(a);
        b = find_set(b);
        if (a != b) {
            if (sizof[a] < sizof[b]){
                swap(a, b);
            }
            parent[b] = a;
            sizof[a] += sizof[b];
        }
    }
};
struct Edge{
    int u,v,w,idx;
    int k,c;
    Edge(int u,int v,int w,int idx) : u(u), v(v), w(w), idx(idx) {}
    Edge() {}
    bool operator<(const Edge &e){
        return w<e.w;
    }
};
void solve(){
    int n,m,k;
    cin>>n>>m>>k;
    vector<vector<Edge>> adj(n);
    vector<Edge> edges(m);
    for(int i=0;i<m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        --u;--v;
        adj[u].pb(Edge(u,v,w,i));
    }
    for(int i=0;i<n;i++){
        sort(adj[i].begin(), adj[i].end());
        for(int j=0;j<(int)adj[i].size();j++){
            adj[i][j].k = adj[i].size() - 1;
            adj[i][j].c = j;
            edges[adj[i][j].idx] = adj[i][j];
        }
    }
    vector<bool> selfedge(11*k + 1);
    const int MAXN = 2e5 + 7;
    vector<bitset<MAXN>> sol(11*k);
    vector<vector<bool>> allow(11*k +1, vector<bool>(11*k + 1, 1));
    auto allowed = [&](const pair<int,int> &x, const pair<int,int> &y){
        if(selfedge[y.first*10 + y.second]) return false;
        return bool(allow[10*x.first + x.second][10*y.first + y.second]);
    };
    for(const auto &e : edges){
        if(sol[10*e.k + e.c][e.v]){
            selfedge[10*e.k + e.c] = 1;
        }
        sol[10*e.k + e.c][e.v] = 1;
    }
    for(int i=0;i<11*k;i++){
        for(const auto &e : edges){
            if(10*e.k + e.c == i) continue;
            if(sol[i][e.v]){
                allow[i][10*e.k + e.c] = 0;
            }
        }
    }
    ll ans = 0;
    function<void(vector<int>&)> recurse = [&](vector<int>& curr){
        if((int)curr.size()==k){
            /*for(const auto &x : curr){
                cout<<x<<" ";
            }
            cout<<"\n";
            */
            ++ans;
            return;
        }
        int idx = curr.size();
        for(int i=0;i<=idx;i++){
            bool poss = 1;
            for(int j=0;j<(int)curr.size();j++){
                if(!allowed({j, curr[j]}, {idx, i})){
                    poss = 0;
                }
            }
            if(!poss) continue;
            curr.pb(i);
            recurse(curr);
            curr.pop_back();
        }
    };
    vector<int> use;
    recurse(use);
    cout<<ans<<"\n";
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
}


#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <complex>
#include <queue>
#include <set>
#include <unordered_set>
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <iomanip>
#include <fstream>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> p32;
typedef pair<ll,ll> p64;
typedef pair<double,double> pdd;
typedef vector<ll> v64;
typedef vector<int> v32;
typedef vector<vector<int> > vv32;
typedef vector<vector<ll> > vv64;
typedef vector<vector<p64> > vvp64;
typedef vector<p64> vp64;
typedef vector<p32> vp32;
ll MOD = 1e12+13;
double eps = 1e-12;
#define forn(i,e) for(ll i = 0; i < e; i++)
#define forsn(i,s,e) for(ll i = s; i < e; i++)
#define rforn(i,s) for(ll i = s; i >= 0; i--)
#define rforsn(i,s,e) for(ll i = s; i >= e; i--)
#define ln "\n"
#define dbg(x) cout<<#x<<" = "<<x<<ln
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define INF 1e18
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((ll)(x).size())

ll mpow(ll a, ll b){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2);
	t1 *= t1;
	t1 %= MOD;
	if(b%2) t1 *= a;
	t1 %= MOD;
	return t1;
}

ll mpow(ll a, ll b, ll p){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2,p);
	t1 *= t1;
	t1 %= p;
	if(b%2) t1 *= a;
	t1 %= p;
	return t1;
}

ll modinverse(ll a, ll m){
	ll m0 = m;
    ll y = 0, x = 1;
    if (m == 1) return 0;
    while (a > 1){
        ll q = a / m;
        ll t = m;
        m = a % m, a = t;
        t = y;
        y = x - q * y;
        x = t;
    }
    if (x < 0) x += m0;
    return x;
}

mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());

ll range(ll l, ll r){
	return l + mt()%(r-l+1);
}

ll rev(ll v){
	return mpow(v,MOD-2);
}

ll curval;
ll k;
ll ans;
ll val[9][9];
ll final;

void f(ll v){
	if(v==k) {
		if(curval == final) ans++;
	}
	else{
		forn(i,v+1){
			curval += val[v][i];
			f(v+1);
			curval -= val[v][i];
		}
	}
}

void solve(){
	ll n,m;
	cin >> n >> m >> k;
	ll a[n];
	forn(i,n) a[i]=mt()%MOD;
	vvp64 gr(n);
	v64 deg(n,0);
	forn(i,m){
		ll u,v,w;
		cin >> u >> v >> w;
		u--,v--;
		gr[u].pb(mp(w,v));
		deg[u]++;
	}
	// forn(i,n) sort(all(gr[i]));
	forn(i,n) {
		deg[i]--;
		forn(j,deg[i]+1){
			val[deg[i]][j]+=a[gr[i][j].se];
			val[deg[i]][j]%=MOD;
		}
	}
	forn(i,n){
		final += a[i];
	}
	f(0);
	cout << ans << ln;
}

int main()
{
	fast_cin();
	ll t=1;
    // cin >> t;
    forn(i,t) {
    	// cout << "Case #" << i+1 << ": ";
    	solve();
    }
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <complex>
#include <queue>
#include <set>
#include <unordered_set>
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <iomanip>
#include <fstream>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> p32;
typedef pair<ll,ll> p64;
typedef pair<double,double> pdd;
typedef vector<ll> v64;
typedef vector<int> v32;
typedef vector<vector<int> > vv32;
typedef vector<vector<ll> > vv64;
typedef vector<vector<p64> > vvp64;
typedef vector<p64> vp64;
typedef vector<p32> vp32;
ll MOD = 1e12+13;
double eps = 1e-12;
#define forn(i,e) for(ll i = 0; i < e; i++)
#define forsn(i,s,e) for(ll i = s; i < e; i++)
#define rforn(i,s) for(ll i = s; i >= 0; i--)
#define rforsn(i,s,e) for(ll i = s; i >= e; i--)
#define ln "\n"
#define dbg(x) cout<<#x<<" = "<<x<<ln
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define INF 1e18
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((ll)(x).size())

ll mpow(ll a, ll b){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2);
	t1 *= t1;
	t1 %= MOD;
	if(b%2) t1 *= a;
	t1 %= MOD;
	return t1;
}

ll mpow(ll a, ll b, ll p){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2,p);
	t1 *= t1;
	t1 %= p;
	if(b%2) t1 *= a;
	t1 %= p;
	return t1;
}

ll modinverse(ll a, ll m){
	ll m0 = m;
    ll y = 0, x = 1;
    if (m == 1) return 0;
    while (a > 1){
        ll q = a / m;
        ll t = m;
        m = a % m, a = t;
        t = y;
        y = x - q * y;
        x = t;
    }
    if (x < 0) x += m0;
    return x;
}

mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());

ll range(ll l, ll r){
	return l + mt()%(r-l+1);
}

ll rev(ll v){
	return mpow(v,MOD-2);
}

ll curval;
ll k;
ll ans;
ll val[9][9];
ll final;

void f(ll v){
	if(v==k) {
		if(curval == final) ans++;
	}
	else{
		forn(i,v+1){
			curval += val[v][i];
			f(v+1);
			curval -= val[v][i];
		}
	}
}

void solve(){
	ll n,m;
	cin >> n >> m >> k;
	ll a[n];
	forn(i,n) a[i]=mt();
	vvp64 gr(n);
	v64 deg(n,0);
	forn(i,m){
		ll u,v,w;
		cin >> u >> v >> w;
		u--,v--;
		gr[u].pb(mp(w,v));
		deg[u]++;
	}
	// forn(i,n) sort(all(gr[i]));
	forn(i,n) {
		deg[i]--;
		forn(j,deg[i]+1){
			val[deg[i]][j]+=a[gr[i][j].se];
		}
	}
	forn(i,n){
		final += a[i];
	}
	f(0);
	cout << ans << ln;
}

int main()
{
	fast_cin();
	ll t=1;
    // cin >> t;
    forn(i,t) {
    	// cout << "Case #" << i+1 << ": ";
    	solve();
    }
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <complex>
#include <queue>
#include <set>
#include <unordered_set>
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <iomanip>
#include <fstream>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> p32;
typedef pair<ll,ll> p64;
typedef pair<double,double> pdd;
typedef vector<ll> v64;
typedef vector<int> v32;
typedef vector<vector<int> > vv32;
typedef vector<vector<ll> > vv64;
typedef vector<vector<p64> > vvp64;
typedef vector<p64> vp64;
typedef vector<p32> vp32;
ll MOD = 1e12+13;
double eps = 1e-12;
#define forn(i,e) for(ll i = 0; i < e; i++)
#define forsn(i,s,e) for(ll i = s; i < e; i++)
#define rforn(i,s) for(ll i = s; i >= 0; i--)
#define rforsn(i,s,e) for(ll i = s; i >= e; i--)
#define ln "\n"
#define dbg(x) cout<<#x<<" = "<<x<<ln
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define INF 1e18
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((ll)(x).size())

ll mpow(ll a, ll b){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2);
	t1 *= t1;
	t1 %= MOD;
	if(b%2) t1 *= a;
	t1 %= MOD;
	return t1;
}

ll mpow(ll a, ll b, ll p){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2,p);
	t1 *= t1;
	t1 %= p;
	if(b%2) t1 *= a;
	t1 %= p;
	return t1;
}

ll modinverse(ll a, ll m){
	ll m0 = m;
    ll y = 0, x = 1;
    if (m == 1) return 0;
    while (a > 1){
        ll q = a / m;
        ll t = m;
        m = a % m, a = t;
        t = y;
        y = x - q * y;
        x = t;
    }
    if (x < 0) x += m0;
    return x;
}

mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());

ll range(ll l, ll r){
	return l + mt()%(r-l+1);
}

ll rev(ll v){
	return mpow(v,MOD-2);
}

ll curval;
ll k;
ll ans;
ll val[9][9];
ll final;

void f(ll v){
	if(v==k) {
		if(curval == final) ans++;
	}
	else{
		forn(i,v+1){
			curval += val[v][i];
			f(v+1);
			curval -= val[v][i];
		}
	}
}

void solve(){
	ll n,m;
	cin >> n >> m >> k;
	ll a[n];
	forn(i,n) a[i]=mt()%MOD;
	vvp64 gr(n);
	v64 deg(n,0);
	forn(i,m){
		ll u,v,w;
		cin >> u >> v >> w;
		u--,v--;
		gr[u].pb(mp(w,v));
		deg[u]++;
	}
	// forn(i,n) sort(all(gr[i]));
	forn(i,n) {
		deg[i]--;
		forn(j,deg[i]+1){
			val[deg[i]][j]+=a[gr[i][j].se];
		}
	}
	forn(i,n){
		final += a[i];
	}
	f(0);
	cout << ans << ln;
}

int main()
{
	fast_cin();
	ll t=1;
    // cin >> t;
    forn(i,t) {
    	// cout << "Case #" << i+1 << ": ";
    	solve();
    }
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <complex>
#include <queue>
#include <set>
#include <unordered_set>
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <iomanip>
#include <fstream>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> p32;
typedef pair<ll,ll> p64;
typedef pair<double,double> pdd;
typedef vector<ll> v64;
typedef vector<int> v32;
typedef vector<vector<int> > vv32;
typedef vector<vector<ll> > vv64;
typedef vector<vector<p64> > vvp64;
typedef vector<p64> vp64;
typedef vector<p32> vp32;
ll MOD = 1e12+13;
double eps = 1e-12;
#define forn(i,e) for(ll i = 0; i < e; i++)
#define forsn(i,s,e) for(ll i = s; i < e; i++)
#define rforn(i,s) for(ll i = s; i >= 0; i--)
#define rforsn(i,s,e) for(ll i = s; i >= e; i--)
#define ln "\n"
#define dbg(x) cout<<#x<<" = "<<x<<ln
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define INF 1e18
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((ll)(x).size())

ll mpow(ll a, ll b){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2);
	t1 *= t1;
	t1 %= MOD;
	if(b%2) t1 *= a;
	t1 %= MOD;
	return t1;
}

ll mpow(ll a, ll b, ll p){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2,p);
	t1 *= t1;
	t1 %= p;
	if(b%2) t1 *= a;
	t1 %= p;
	return t1;
}

ll modinverse(ll a, ll m){
	ll m0 = m;
    ll y = 0, x = 1;
    if (m == 1) return 0;
    while (a > 1){
        ll q = a / m;
        ll t = m;
        m = a % m, a = t;
        t = y;
        y = x - q * y;
        x = t;
    }
    if (x < 0) x += m0;
    return x;
}

mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());

ll range(ll l, ll r){
	return l + mt()%(r-l+1);
}

ll rev(ll v){
	return mpow(v,MOD-2);
}

ll curval;
ll k;
ll ans;
ll val[9][9];
ll final;

void f(ll v){
	if(v==k) {
		if(curval == final) ans++;
	}
	else{
		forn(i,v+1){
			curval += val[v][i];
			curval %= MOD;
			f(v+1);
			curval += (MOD-val[v][i]);
			curval %= MOD;
		}
	}
}

void solve(){
	ll n,m;
	cin >> n >> m >> k;
	ll a[n];
	forn(i,n) a[i]=mt()%MOD;
	vvp64 gr(n);
	v64 deg(n,0);
	forn(i,m){
		ll u,v,w;
		cin >> u >> v >> w;
		u--,v--;
		gr[u].pb(mp(w,v));
		deg[u]++;
	}
	forn(i,n) sort(all(gr[i]));
	forn(i,n) {
		deg[i]--;
		forn(j,deg[i]+1){
			val[deg[i]][j]+=a[gr[i][j].se];
			val[deg[i]][j]%=MOD;
		}
	}
	forn(i,n){
		final += a[i];
		final %= MOD;
	}
	f(0);
	cout << ans << ln;
}

int main()
{
	fast_cin();
	ll t=1;
    // cin >> t;
    forn(i,t) {
    	// cout << "Case #" << i+1 << ": ";
    	solve();
    }
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <complex>
#include <queue>
#include <set>
#include <unordered_set>
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <iomanip>
#include <fstream>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> p32;
typedef pair<ll,ll> p64;
typedef pair<double,double> pdd;
typedef vector<ll> v64;
typedef vector<int> v32;
typedef vector<vector<int> > vv32;
typedef vector<vector<ll> > vv64;
typedef vector<vector<p64> > vvp64;
typedef vector<p64> vp64;
typedef vector<p32> vp32;
ll MOD = 1e12+13;
double eps = 1e-12;
#define forn(i,e) for(ll i = 0; i < e; i++)
#define forsn(i,s,e) for(ll i = s; i < e; i++)
#define rforn(i,s) for(ll i = s; i >= 0; i--)
#define rforsn(i,s,e) for(ll i = s; i >= e; i--)
#define ln "\n"
#define dbg(x) cout<<#x<<" = "<<x<<ln
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define INF 1e18
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((ll)(x).size())

ll mpow(ll a, ll b){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2);
	t1 *= t1;
	t1 %= MOD;
	if(b%2) t1 *= a;
	t1 %= MOD;
	return t1;
}

ll mpow(ll a, ll b, ll p){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2,p);
	t1 *= t1;
	t1 %= p;
	if(b%2) t1 *= a;
	t1 %= p;
	return t1;
}

ll modinverse(ll a, ll m){
	ll m0 = m;
    ll y = 0, x = 1;
    if (m == 1) return 0;
    while (a > 1){
        ll q = a / m;
        ll t = m;
        m = a % m, a = t;
        t = y;
        y = x - q * y;
        x = t;
    }
    if (x < 0) x += m0;
    return x;
}

mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());

ll range(ll l, ll r){
	return l + mt()%(r-l+1);
}

ll rev(ll v){
	return mpow(v,MOD-2);
}

ll curval;
ll k;
ll ans;
ll val[9][9];
ll final;

void f(ll v){
	if(v==k) {
		if(curval == final) ans++;
	}
	else{
		forn(i,v+1){
			curval += val[v][i];
			curval %= MOD;
			f(v+1);
			curval += (MOD-val[v][i]);
			curval %= MOD;
		}
	}
}

void solve(){
	ll n,m;
	cin >> n >> m >> k;
	ll a[n];
	forn(i,n) a[i]=mt()%MOD;
	vvp64 gr(n);
	v64 deg(n,0);
	forn(i,m){
		ll u,v,w;
		cin >> u >> v >> w;
		u--,v--;
		gr[u].pb(mp(w,v));
		deg[u]++;
	}
	// forn(i,n) sort(all(gr[i]));
	forn(i,n) {
		deg[i]--;
		forn(j,deg[i]+1){
			val[deg[i]][j]+=a[gr[i][j].se];
			val[deg[i]][j]%=MOD;
		}
	}
	forn(i,n){
		final += a[i];
		final %= MOD;
	}
	f(0);
	cout << ans << ln;
}

int main()
{
	fast_cin();
	ll t=1;
    // cin >> t;
    forn(i,t) {
    	// cout << "Case #" << i+1 << ": ";
    	solve();
    }
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <complex>
#include <queue>
#include <set>
#include <unordered_set>
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <iomanip>
#include <fstream>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> p32;
typedef pair<ll,ll> p64;
typedef pair<double,double> pdd;
typedef vector<ll> v64;
typedef vector<int> v32;
typedef vector<vector<int> > vv32;
typedef vector<vector<ll> > vv64;
typedef vector<vector<p64> > vvp64;
typedef vector<p64> vp64;
typedef vector<p32> vp32;
ll MOD = 1e12+13;
double eps = 1e-12;
#define forn(i,e) for(ll i = 0; i < e; i++)
#define forsn(i,s,e) for(ll i = s; i < e; i++)
#define rforn(i,s) for(ll i = s; i >= 0; i--)
#define rforsn(i,s,e) for(ll i = s; i >= e; i--)
#define ln "\n"
#define dbg(x) cout<<#x<<" = "<<x<<ln
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define INF 1e18
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((ll)(x).size())

ll mpow(ll a, ll b){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2);
	t1 *= t1;
	t1 %= MOD;
	if(b%2) t1 *= a;
	t1 %= MOD;
	return t1;
}

ll mpow(ll a, ll b, ll p){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2,p);
	t1 *= t1;
	t1 %= p;
	if(b%2) t1 *= a;
	t1 %= p;
	return t1;
}

ll modinverse(ll a, ll m){
	ll m0 = m;
    ll y = 0, x = 1;
    if (m == 1) return 0;
    while (a > 1){
        ll q = a / m;
        ll t = m;
        m = a % m, a = t;
        t = y;
        y = x - q * y;
        x = t;
    }
    if (x < 0) x += m0;
    return x;
}

mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());

ll range(ll l, ll r){
	return l + mt()%(r-l+1);
}

ll rev(ll v){
	return mpow(v,MOD-2);
}

bool allow[9][9][9][9];
bool possible[9][9];
v64 vec;
ll k;
ll ans;

void f(){
	if(sz(vec)==k) ans++;
	else{
		forn(i,sz(vec)+1){
			bool bo = 0;
			if(!possible[sz(vec)][i]) bo=1;
			forn(j,sz(vec)){
				if(!allow[j][vec[j]][sz(vec)][i]) bo=1;
			}
			if(bo) continue;
			vec.pb(i);
			f();
			vec.pop_back();
		}
	}
}

void solve(){
	ll n,m;
	cin >> n >> m >> k;
	vvp64 gr(n);
	v64 deg(n,0);
	forn(i,m){
		ll u,v,w;
		cin >> u >> v >> w;
		u--,v--;
		gr[u].pb(mp(w,v));
		deg[u]++;
	}
	forn(i,n) deg[i]--;
	forn(i,n) sort(all(gr[i]));
	multiset<p64> s[n];
	forn(i,n){
		forn(j,sz(gr[i])){
			s[gr[i][j].se].insert(mp(deg[i],j));
		}
	}
	forn(i,9) forn(j,9) forn(k,9) forn(l,9) allow[i][j][k][l]=2;
	forn(i,9) forn(j,9) possible[i][j]=1;
	forn(i,n){
		set<p64> temp;
		for(auto it1 : s[i]){
			if(temp.find(it1)!=temp.end()){
				possible[it1.fi][it1.se]=0;
			}
			else{
				for(auto it2 : temp){
					allow[it2.fi][it2.se][it1.fi][it1.se] = 0;
				}
				temp.insert(it1);
			}
		}
	}
	f();
	cout << ans << ln;
}

int main()
{
	fast_cin();
	ll t=1;
    // cin >> t;
    forn(i,t) {
    	// cout << "Case #" << i+1 << ": ";
    	solve();
    }
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <complex>
#include <queue>
#include <set>
#include <unordered_set>
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <iomanip>
#include <fstream>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> p32;
typedef pair<ll,ll> p64;
typedef pair<double,double> pdd;
typedef vector<ll> v64;
typedef vector<int> v32;
typedef vector<vector<int> > vv32;
typedef vector<vector<ll> > vv64;
typedef vector<vector<p64> > vvp64;
typedef vector<p64> vp64;
typedef vector<p32> vp32;
ll MOD = 1e12+13;
double eps = 1e-12;
#define forn(i,e) for(ll i = 0; i < e; i++)
#define forsn(i,s,e) for(ll i = s; i < e; i++)
#define rforn(i,s) for(ll i = s; i >= 0; i--)
#define rforsn(i,s,e) for(ll i = s; i >= e; i--)
#define ln "\n"
#define dbg(x) cout<<#x<<" = "<<x<<ln
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define INF 1e18
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((ll)(x).size())

ll mpow(ll a, ll b){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2);
	t1 *= t1;
	t1 %= MOD;
	if(b%2) t1 *= a;
	t1 %= MOD;
	return t1;
}

ll mpow(ll a, ll b, ll p){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2,p);
	t1 *= t1;
	t1 %= p;
	if(b%2) t1 *= a;
	t1 %= p;
	return t1;
}

ll modinverse(ll a, ll m){
	ll m0 = m;
    ll y = 0, x = 1;
    if (m == 1) return 0;
    while (a > 1){
        ll q = a / m;
        ll t = m;
        m = a % m, a = t;
        t = y;
        y = x - q * y;
        x = t;
    }
    if (x < 0) x += m0;
    return x;
}

mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());

ll range(ll l, ll r){
	return l + mt()%(r-l+1);
}

ll rev(ll v){
	return mpow(v,MOD-2);
}

bool allow[9][9][9][9];
bool possible[9][9];
v64 vec;
ll k;
ll ans;

void f(){
	if(sz(vec)==k) ans++;
	else{
		forn(i,sz(vec)+1){
			bool bo = 0;
			if(!possible[sz(vec)][i]) bo=1;
			forn(j,sz(vec)){
				if(!allow[j][vec[j]][sz(vec)][i]) bo=1;
			}
			if(bo) continue;
			vec.pb(i);
			f();
			vec.pop_back();
		}
	}
}

void solve(){
	ll n,m;
	cin >> n >> m >> k;
	vvp64 gr(n);
	v64 deg(n,0);
	forn(i,m){
		ll u,v,w;
		cin >> u >> v >> w;
		u--,v--;
		gr[u].pb(mp(w,v));
		deg[u]++;
	}
	forn(i,n) deg[i]--;
	forn(i,n) sort(all(gr[i]));
	multiset<p64> s[n];
	forn(i,n){
		forn(j,sz(gr[i])){
			s[gr[i][j].se].insert(mp(deg[i],j));
		}
	}
	forn(i,9) forn(j,9) forn(k,9) forn(l,9) allow[i][j][k][l]=2;
	forn(i,9) forn(j,9) possible[i][j]=1;
	forn(i,n){
		vp64 temp;
		for(auto it1 : s[i]){
			for(auto it2 : temp){
				if(it1.fi == it2.fi && it1.se == it2.se){
					possible[it1.fi][it1.se]=0;
				}
				allow[it2.fi][it2.se][it1.fi][it1.se] = 0;
			}
			temp.pb(it1);
		}
	}
	f();
	cout << ans << ln;
}

int main()
{
	fast_cin();
	ll t=1;
    // cin >> t;
    forn(i,t) {
    	// cout << "Case #" << i+1 << ": ";
    	solve();
    }
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <complex>
#include <queue>
#include <set>
#include <unordered_set>
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <iomanip>
#include <fstream>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> p32;
typedef pair<ll,ll> p64;
typedef pair<double,double> pdd;
typedef vector<ll> v64;
typedef vector<int> v32;
typedef vector<vector<int> > vv32;
typedef vector<vector<ll> > vv64;
typedef vector<vector<p64> > vvp64;
typedef vector<p64> vp64;
typedef vector<p32> vp32;
ll MOD = 1e12+13;
double eps = 1e-12;
#define forn(i,e) for(ll i = 0; i < e; i++)
#define forsn(i,s,e) for(ll i = s; i < e; i++)
#define rforn(i,s) for(ll i = s; i >= 0; i--)
#define rforsn(i,s,e) for(ll i = s; i >= e; i--)
#define ln "\n"
#define dbg(x) cout<<#x<<" = "<<x<<ln
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define INF 1e18
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((ll)(x).size())

ll mpow(ll a, ll b){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2);
	t1 *= t1;
	t1 %= MOD;
	if(b%2) t1 *= a;
	t1 %= MOD;
	return t1;
}

ll mpow(ll a, ll b, ll p){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2,p);
	t1 *= t1;
	t1 %= p;
	if(b%2) t1 *= a;
	t1 %= p;
	return t1;
}

ll modinverse(ll a, ll m){
	ll m0 = m;
    ll y = 0, x = 1;
    if (m == 1) return 0;
    while (a > 1){
        ll q = a / m;
        ll t = m;
        m = a % m, a = t;
        t = y;
        y = x - q * y;
        x = t;
    }
    if (x < 0) x += m0;
    return x;
}

mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());

ll range(ll l, ll r){
	return l + mt()%(r-l+1);
}

ll rev(ll v){
	return mpow(v,MOD-2);
}

ll allow[9][9][9];
bool possible[9][9];

ll f(ll in, ll val, ll k, v64 vec){
	// cout << in << " "<< val << ln;
	if((vec[in]&(1<<val)) && possible[in][val]){
		// if(in==k-1) cout << val << ln;
		if(in==k-1) return 1;
		v64 temp = vec;
		forsn(j,in+1,k){
			temp[j] &= (allow[in][val][j]);
		}
		ll ans = 0;
		forn(i,in+2){
			ans += f(in+1,i,k,temp);
		}
		return ans;
	}
	else{
		return 0;
	}
}

void solve(){
	ll n,m,k;
	cin >> n >> m >> k;
	vvp64 gr(n);
	v64 deg(n,0);
	forn(i,m){
		ll u,v,w;
		cin >> u >> v >> w;
		u--,v--;
		gr[u].pb(mp(w,v));
		deg[u]++;
	}
	forn(i,n) deg[i]--;
	forn(i,n) sort(all(gr[i]));
	multiset<p64> s[n];
	forn(i,n){
		forn(j,sz(gr[i])){
			// cout << i << " " << gr[i][j].se << " " << deg[i] << " " << j << ln;
			s[gr[i][j].se].insert(mp(deg[i],j));
		}
	}
	ll full = (1<<9)-1;
	// cout << full << ln;
	forn(i,9) forn(j,9) forn(k,9) allow[i][j][k]=full;
	forn(i,9) forn(j,9) possible[i][j]=1;
	// cout << allow[0][0][2] << ln;
	forn(i,n){
		vp64 temp;
		// cout << i << ln;
		for(auto it1 : s[i]){
			// cout << it1.fi << " " << it1.se << "          ";
			for(auto it2 : temp){
				if(it1.fi == it2.fi && it1.se == it2.se){
					possible[it1.fi][it1.se]=0;
				}
				allow[it2.fi][it2.se][it1.fi] &= (full^(1 << (it1.se)));
			}
			temp.pb(it1);
		}
		// cout << ln;
	}
	// cout << allow[0][0][2] << ln;
	v64 vec;
	forn(i,k) vec.pb(full);
	cout << f(0,0,k,vec) << ln;
}

int main()
{
	fast_cin();
	ll t=1;
    // cin >> t;
    forn(i,t) {
    	// cout << "Case #" << i+1 << ": ";
    	solve();
    }
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <complex>
#include <queue>
#include <set>
#include <unordered_set>
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <iomanip>
#include <fstream>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> p32;
typedef pair<ll,ll> p64;
typedef pair<double,double> pdd;
typedef vector<ll> v64;
typedef vector<int> v32;
typedef vector<vector<int> > vv32;
typedef vector<vector<ll> > vv64;
typedef vector<vector<p64> > vvp64;
typedef vector<p64> vp64;
typedef vector<p32> vp32;
ll MOD = 1e12+13;
double eps = 1e-12;
#define forn(i,e) for(ll i = 0; i < e; i++)
#define forsn(i,s,e) for(ll i = s; i < e; i++)
#define rforn(i,s) for(ll i = s; i >= 0; i--)
#define rforsn(i,s,e) for(ll i = s; i >= e; i--)
#define ln "\n"
#define dbg(x) cout<<#x<<" = "<<x<<ln
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define INF 1e18
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((ll)(x).size())

ll mpow(ll a, ll b){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2);
	t1 *= t1;
	t1 %= MOD;
	if(b%2) t1 *= a;
	t1 %= MOD;
	return t1;
}

ll mpow(ll a, ll b, ll p){
	if(a==0) return 0;
	if(b==0) return 1;
	ll t1 = mpow(a,b/2,p);
	t1 *= t1;
	t1 %= p;
	if(b%2) t1 *= a;
	t1 %= p;
	return t1;
}

ll modinverse(ll a, ll m){
	ll m0 = m;
    ll y = 0, x = 1;
    if (m == 1) return 0;
    while (a > 1){
        ll q = a / m;
        ll t = m;
        m = a % m, a = t;
        t = y;
        y = x - q * y;
        x = t;
    }
    if (x < 0) x += m0;
    return x;
}

mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());

ll range(ll l, ll r){
	return l + mt()%(r-l+1);
}

ll rev(ll v){
	return mpow(v,MOD-2);
}

ll allow[9][9][9];
bool possible[9][9];
v64 vec;
ll k;

ll f(ll in, ll val){
	// cout << in << " "<< val << ln;
	if((vec[in]&(1<<val)) && possible[in][val]){
		// if(in==k-1) cout << val << ln;
		if(in==k-1) return 1;
		v64 temp = vec;
		forsn(j,in+1,k){
			vec[j] &= (allow[in][val][j]);
		}
		ll ans = 0;
		forn(i,in+2){
			ans += f(in+1,i);
		}
		vec = temp;
		return ans;
	}
	else{
		return 0;
	}
}

void solve(){
	ll n,m;
	cin >> n >> m >> k;
	vvp64 gr(n);
	v64 deg(n,0);
	forn(i,m){
		ll u,v,w;
		cin >> u >> v >> w;
		u--,v--;
		gr[u].pb(mp(w,v));
		deg[u]++;
	}
	forn(i,n) deg[i]--;
	forn(i,n) sort(all(gr[i]));
	multiset<p64> s[n];
	forn(i,n){
		forn(j,sz(gr[i])){
			// cout << i << " " << gr[i][j].se << " " << deg[i] << " " << j << ln;
			s[gr[i][j].se].insert(mp(deg[i],j));
		}
	}
	ll full = (1<<9)-1;
	// cout << full << ln;
	forn(i,9) forn(j,9) forn(k,9) allow[i][j][k]=full;
	forn(i,9) forn(j,9) possible[i][j]=1;
	// cout << allow[0][0][2] << ln;
	forn(i,n){
		vp64 temp;
		// cout << i << ln;
		for(auto it1 : s[i]){
			// cout << it1.fi << " " << it1.se << "          ";
			for(auto it2 : temp){
				if(it1.fi == it2.fi && it1.se == it2.se){
					possible[it1.fi][it1.se]=0;
				}
				allow[it2.fi][it2.se][it1.fi] &= (full^(1 << (it1.se)));
			}
			temp.pb(it1);
		}
		// cout << ln;
	}
	// cout << allow[0][0][2] << ln;
	forn(i,k) vec.pb(full);
	cout << f(0,0) << ln;
}

int main()
{
	fast_cin();
	ll t=1;
    // cin >> t;
    forn(i,t) {
    	// cout << "Case #" << i+1 << ": ";
    	solve();
    }
    return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <set>
#include <cstring>
#include <map>
#include <queue>
#include <cassert>
#include <bitset>

using namespace std;

const int MOD = (int)1e9 + 7;

int n, m, k, x, y, z, ans, S;

vector <pair <int, int>> g[200005];
long long s[20][20], sp[20][20];
int sx[20][20];

bool comp(pair <int, int> a, pair <int, int> b) {
  return a.second < b.second;
}

void bkt(int niv, long long s1, long long s2, int s3) {
  if(niv == k + 1) {
    ans += (s1 == 1LL * n * (n + 1) / 2 && s2 == 1LL * n * (n + 1) * (2 * n + 1) / 6 && s3 == S);
    return;
  }
  for(int i = 1; i <= niv; i++)
    bkt(niv + 1, s1 + s[niv][i], s2 + sp[niv][i], s3 ^ sx[niv][i]);
}

int main() {
  ios_base :: sync_with_stdio(false);
  cin.tie(0); cout.tie(0);
  cin >> n >> m >> k;
  for(; m; m--) {
    cin >> x >> y >> z;
    g[x].push_back({y, z});
  }
  for(int i = 1; i <= n; i++)
    sort(g[i].begin(), g[i].end(), comp), S ^= i;
  for(int i = 1; i <= n; i++) {
    for(int j = 0; j < g[i].size(); j++) {
      s[g[i].size()][j + 1] += g[i][j].first;
      sp[g[i].size()][j + 1] += 1LL * g[i][j].first * g[i][j].first;
      sx[g[i].size()][j + 1] ^= g[i][j].first;
      prod[g[i].size()][j + 1] = 1LL * prod[g[i].size()][j + 1] % MOD;
    }
  }
  bkt(1, 0, 0, 0);
  cout << ans;
  return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <set>
#include <cstring>
#include <map>
#include <queue>
#include <bitset>

using namespace std;

int n, m, k, x, y, z, ans;

vector <pair <int, int>> g[200005];
long long s[10][10];
int v[10];
long long sp[10][10];

bool comp(pair <int, int> a, pair <int, int> b) {
  return a.second < b.second;
}

void bkt(int niv) {
  if(niv == k + 1) {
    long long s1 = 0, s2 = 0;
    for(int i = 1; i <= k; i++)
      s1 += s[i][v[i]], s2 += sp[i][v[i]];
    ans += (s1 == 1LL * n * (n + 1) / 2 && s2 == 1LL * n * (n + 1) * (2 * n + 1) / 6);
    return;
  }
  for(int i = 1; i <= niv; i++) {
    v[niv] = i;
    bkt(niv + 1);
  }
}

int main() {
  ios_base :: sync_with_stdio(false);
  cin.tie(0); cout.tie(0);
  cin >> n >> m >> k;
  for(; m; m--) {
    cin >> x >> y >> z;
    g[x].push_back({y, z});
  }
  for(int i = 1; i <= n; i++)
    sort(g[i].begin(), g[i].end(), comp);
  for(int i = 1; i <= n; i++) {
    for(int j = 0; j < g[i].size(); j++) {
      s[g[i].size()][j + 1] += g[i][j].first;
      sp[g[i].size()][j + 1] += 1LL * g[i][j].first * g[i][j].first;
    }
  }
  bkt(1);
  cout << ans;
  return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <set>
#include <cstring>
#include <map>
#include <queue>
#include <cassert>
#include <bitset>

using namespace std;

int n, m, k, x, y, z, ans, S;

vector <pair <int, int>> g[200005];
long long s[20][20], sp[20][20];
int sx[20][20];

bool comp(pair <int, int> a, pair <int, int> b) {
  return a.second < b.second;
}

void bkt(int niv, long long s1, long long s2, int s3) {
  if(niv == k + 1) {
    ans += (s1 == 1LL * n * (n + 1) / 2 && s2 == 1LL * n * (n + 1) * (2 * n + 1) / 6 && s3 == S);
    return;
  }
  for(int i = 1; i <= niv; i++)
    bkt(niv + 1, s1 + s[niv][i], s2 + sp[niv][i], s3 ^ sx[niv][i]);
}

int main() {
  ios_base :: sync_with_stdio(false);
  cin.tie(0); cout.tie(0);
  cin >> n >> m >> k;
  for(; m; m--) {
    cin >> x >> y >> z;
    g[x].push_back({y, z});
  }
  for(int i = 1; i <= n; i++)
    sort(g[i].begin(), g[i].end(), comp), S ^= i;
  for(int i = 1; i <= n; i++) {
    for(int j = 0; j < g[i].size(); j++) {
      s[g[i].size()][j + 1] += g[i][j].first;
      sp[g[i].size()][j + 1] += 1LL * g[i][j].first * g[i][j].first;
      sx[g[i].size()][j + 1] ^= g[i][j].first;
    }
  }
  bkt(1, 0, 0, 0);
  cout << ans;
  return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <set>
#include <cstring>
#include <map>
#include <queue>
#include <cassert>
#include <bitset>

using namespace std;

const int MOD = (int)1e9 + 7;

int n, m, k, x, y, z, ans, S;

vector <pair <int, int>> g[200005];
long long s[20][20], sp[20][20];
int prod[20][20];
int sx[20][20];

bool comp(pair <int, int> a, pair <int, int> b) {
  return a.second < b.second;
}

void bkt(int niv, long long s1, long long s2, int s3) {
  if(niv == k + 1) {
    ans += (s1 == 1LL * n * (n + 1) / 2 && s2 == 1LL * n * (n + 1) * (2 * n + 1) / 6 && s3 == S);
    return;
  }
  for(int i = 1; i <= niv; i++)
    bkt(niv + 1, s1 + s[niv][i], s2 + sp[niv][i], s3 ^ sx[niv][i]);
}

int main() {
  ios_base :: sync_with_stdio(false);
  cin.tie(0); cout.tie(0);
  cin >> n >> m >> k;
  for(; m; m--) {
    cin >> x >> y >> z;
    g[x].push_back({y, z});
  }
  for(int i = 1; i <= n; i++)
    sort(g[i].begin(), g[i].end(), comp), S ^= i;
  for(int i = 1; i <= n; i++) {
    for(int j = 0; j < g[i].size(); j++) {
      s[g[i].size()][j + 1] += g[i][j].first;
      sp[g[i].size()][j + 1] += 1LL * g[i][j].first * g[i][j].first;
      sx[g[i].size()][j + 1] ^= g[i][j].first;
      prod[g[i].size()][j + 1] = 1LL * prod[g[i].size()][j + 1] % MOD;
    }
  }
  bkt(1, 0, 0, 0);
  cout << ans;
  return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <set>
#include <cstring>
#include <map>
#include <queue>
#include <cassert>
#include <bitset>

using namespace std;

const int MOD = (int)1e9 + 7;

int n, m, k, x, y, z, ans, S, P;

vector <pair <int, int>> g[200005];
long long s[20][20], sp[20][20];
int prod[20][20];
int sx[20][20];

bool comp(pair <int, int> a, pair <int, int> b) {
  return a.second < b.second;
}

void bkt(int niv, long long s1, long long s2, int s3, int p) {
  if(niv == k + 1) {
    ans += (s1 == 1LL * n * (n + 1) / 2 && s2 == 1LL * n * (n + 1) * (2 * n + 1) / 6 && s3 == S && p == P);
    return;
  }
  for(int i = 1; i <= niv; i++)
    bkt(niv + 1, s1 + s[niv][i], s2 + sp[niv][i], s3 ^ sx[niv][i], 1LL * p * prod[niv][i] % MOD);
}

int main() {
  ios_base :: sync_with_stdio(false);
  cin.tie(0); cout.tie(0);
  cin >> n >> m >> k;
  for(; m; m--) {
    cin >> x >> y >> z;
    g[x].push_back({y, z});
  }
  P = 1;
  for(int i = 1; i <= n; i++)
    sort(g[i].begin(), g[i].end(), comp), S ^= i, P = 1LL * P * i % MOD;
  for(int i = 1; i <= k; i++) {
    for(int j = 1; j <= i; j++)
      prod[i][j] = 1;
  }
  for(int i = 1; i <= n; i++) {
    for(int j = 0; j < g[i].size(); j++) {
      s[g[i].size()][j + 1] += g[i][j].first;
      sp[g[i].size()][j + 1] += 1LL * g[i][j].first * g[i][j].first;
      sx[g[i].size()][j + 1] ^= g[i][j].first;
      prod[g[i].size()][j + 1] = 1LL * prod[g[i].size()][j + 1] * g[i][j].first % MOD;
    }
  }
  bkt(1, 0, 0, 0, 1);
  cout << ans;
  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 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) 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 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();
}


#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int inf=1e9,dx[]={-1,0,1,0},dy[]={0,-1,0,1};
const long long llinf=1e18;
int n,cnt,deep,start;
char x,y;
string s[105],ans;
pair<char,char> order[105];
vector<int> v[30];
int u[30];;
bool ok;
pair<char,char> f(string a,string b)
{
	int i;
	if(a.size()==b.size())
	{
		for(i=0;a[i]==b[i];i++);
		return make_pair(a[i],b[i]);
	}
	else if(a.size()>b.size())
	{
		for(i=0;a[i]==b[i]&&i<b.size();i++);
		if(i==b.size())
		{
			ans="Impossible";
			return make_pair('|','|');
		}
		return make_pair(a[i],b[i]);
	}
	else
	{
		for(i=0;a[i]==b[i]&&i<a.size();i++);
		if(i==a.size())
			return make_pair('|','|');
		return make_pair(a[i],b[i]);
	}
}
void dfs(int x)
{
	ans+=char(x+'a'-1);
	u[x]=1;
	for(int i=0;i<v[x].size();i++)
		if(!u[v[x][i]])
			dfs(v[x][i]);
		else if(u[v[x][i]]==1)
		{
			cout<<"Impossible";
			exit(0);
		}
	u[x]=2;
}
int main(){
	cin>>n;
	cin>>s[1];
	for(int i=2;i<=n;i++)
	{
		cin>>s[i];
		order[i-1]=f(s[i-1],s[i]);
	}
	if(ans=="Impossible")
	{
		cout<<ans;
		return 0;
	}
	for(int i=1;i<n;i++)
	{
		x=order[i].first,y=order[i].second;
		if(x==y)
			continue;
		v[x-'a'+1].push_back(y-'a'+1);
		ok=true;
	}
	if(!ok)
	{
		cout<<"abcdefghijklmnopqrstuvwxyz";
		return 0;
	}
	start=1;
	while(start<n)
	{
		if(order[start].first!=order[start].second&&!u[order[start].first-'a'+1])
			dfs(order[start].first-'a'+1);
		start++;
	}
	for(int i=1;i<=26;i++)
		if(!u[i])
			dfs(i);
	if(ans.size()!=26)
	{
		cout<<"Impossible";
		return 0;
	}
	cout<<ans;
	return 0;
}


#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int inf=1e9,dx[]={-1,0,1,0},dy[]={0,-1,0,1};
const long long llinf=1e18;
int n,cnt,deep,start;
char x,y;
string s[105],ans;
pair<char,char> order[105];
vector<int> v[30];
bool u[30],ok,ok2;
pair<char,char> f(string a,string b)
{
	int i;
	if(a.size()==b.size())
	{
		for(i=0;a[i]==b[i];i++);
		return make_pair(a[i],b[i]);
	}
	else if(a.size()>b.size())
	{
		for(i=0;a[i]==b[i]&&i<b.size();i++);
		if(i==b.size())
		{
			ans="Impossible";
			return make_pair('|','|');
		}
		return make_pair(a[i],b[i]);
	}
	else
	{
		for(i=0;a[i]==b[i]&&i<a.size();i++);
		if(i==a.size())
			return make_pair('|','|');
		return make_pair(a[i],b[i]);
	}
}
void dfs(int x)
{
	ans+=char(x+'a'-1);
	u[x]=true;
	for(int i=0;i<v[x].size();i++)
		if(u[v[x][i]])
		{
			cout<<"Impossible";
			exit(0);
		}
		else
			dfs(v[x][i]);
}
int main(){
	cin>>n;
	cin>>s[1];
	for(int i=2;i<=n;i++)
	{
		cin>>s[i];
		order[i-1]=f(s[i-1],s[i]);
	}
	if(ans=="Impossible")
	{
		cout<<ans;
		return 0;
	}
	for(int i=1;i<n;i++)
	{
		x=order[i].first,y=order[i].second;
		if(x==y)
			continue;
		if(x>y)
			ok2=true;
		v[x-'a'+1].push_back(y-'a'+1);
		ok=true;
	}
	if(!ok||!ok2)
	{
		cout<<"abcdefghijklmnopqrstuvwxyz";
		return 0;
	}
	start=1;
	while(order[start].first==order[start].second)
		start++;
	dfs(order[start].first-'a'+1);
	for(int i=1;i<=26;i++)
		if(!u[i])
			ans+=char(i+'a'-1);
	cout<<ans;
	return 0;
}


#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int inf=1e9,dx[]={-1,0,1,0},dy[]={0,-1,0,1};
const long long llinf=1e18;
int n,cnt;
char x,y;
string s[105],ans;
pair<char,char> order[105];
vector<int> v[30];
bool u[30];
pair<char,char> f(string a,string b)
{
	int i;
	if(a.size()==b.size())
	{
		for(i=0;a[i]==b[i];i++);
		return make_pair(a[i],b[i]);
	}
	else if(a.size()>b.size())
	{
		for(i=0;a[i]==b[i]&&i<b.size();i++);
		if(i==b.size())
		{
			ans="Impossible";
			return make_pair(' ',' ');
		}
		return make_pair(a[i],b[i]);
	}
	else
	{
		for(i=0;a[i]==b[i]&&i<a.size();i++);
		if(i==a.size())
			return make_pair(' ',' ');
		return make_pair(a[i],b[i]);
	}
}
void dfs(int x)
{
	ans+=char(x+'a'-1);
	u[x]=true;
	for(int i=0;i<v[x].size();i++)
		if(u[i])
		{
			cout<<"Impossible";
			exit(0);
		}
		else
			dfs(v[x][i]);
}
int main(){
	cin>>n;
	cin>>s[1];
	for(int i=2;i<=n;i++)
	{
		cin>>s[i];
		order[i-1]=f(s[i-1],s[i]);
	}
	if(ans=="Impossible")
	{
		cout<<ans;
		return 0;
	}
	for(int i=1;i<n;i++)
	{
		x=order[i].first,y=order[i].second;
		if(x==y)
			continue;
		v[x-'a'+1].push_back(y-'a'+1);
	}
	dfs(order[1].first-'a'+1);
	for(int i=1;i<=26;i++)
		if(!u[i])
			ans+=char(i+'a'-1);
	cout<<ans;
	return 0;
}


#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int inf=1e9,dx[]={-1,0,1,0},dy[]={0,-1,0,1};
const long long llinf=1e18;
int n,cnt,deep,start;
char x,y;
string s[105],ans;
pair<char,char> order[105];
vector<int> v[30];
bool u[30],ok;
pair<char,char> f(string a,string b)
{
	int i;
	if(a.size()==b.size())
	{
		for(i=0;a[i]==b[i];i++);
		return make_pair(a[i],b[i]);
	}
	else if(a.size()>b.size())
	{
		for(i=0;a[i]==b[i]&&i<b.size();i++);
		if(i==b.size())
		{
			ans="Impossible";
			return make_pair('|','|');
		}
		return make_pair(a[i],b[i]);
	}
	else
	{
		for(i=0;a[i]==b[i]&&i<a.size();i++);
		if(i==a.size())
			return make_pair('|','|');
		return make_pair(a[i],b[i]);
	}
}
void dfs(int x)
{
	ans+=char(x+'a'-1);
	u[x]=true;
	for(int i=0;i<v[x].size();i++)
		if(!u[v[x][i]])
			dfs(v[x][i]);
}
int main(){
	cin>>n;
	cin>>s[1];
	for(int i=2;i<=n;i++)
	{
		cin>>s[i];
		order[i-1]=f(s[i-1],s[i]);
	}
	if(ans=="Impossible")
	{
		cout<<ans;
		return 0;
	}
	for(int i=1;i<n;i++)
	{
		x=order[i].first,y=order[i].second;
		if(x==y)
			continue;
		v[x-'a'+1].push_back(y-'a'+1);
		ok=true;
	}
	if(!ok)
	{
		cout<<"abcdefghijklmnopqrstuvwxyz";
		return 0;
	}
	start=1;
	while(start<n)
	{
		if(order[start].first!=order[start].second&&!u[order[start].first-'a'+1])
			dfs(order[start].first-'a'+1);
		start++;
	}
	for(int i=1;i<=26;i++)
		if(!u[i])
			dfs(i);
	if(ans.size()!=26)
	{
		cout<<"Impossible";
		return 0;
	}
	cout<<ans;
	return 0;
}


#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int inf=1e9,dx[]={-1,0,1,0},dy[]={0,-1,0,1};
const long long llinf=1e18;
int n,cnt,deep,start;
char x,y;
string s[105],ans;
pair<char,char> order[105];
vector<int> v[30];
bool u[30];
pair<char,char> f(string a,string b)
{
	int i;
	if(a.size()==b.size())
	{
		for(i=0;a[i]==b[i];i++);
		return make_pair(a[i],b[i]);
	}
	else if(a.size()>b.size())
	{
		for(i=0;a[i]==b[i]&&i<b.size();i++);
		if(i==b.size())
		{
			ans="Impossible";
			return make_pair('|','|');
		}
		return make_pair(a[i],b[i]);
	}
	else
	{
		for(i=0;a[i]==b[i]&&i<a.size();i++);
		if(i==a.size())
			return make_pair('|','|');
		return make_pair(a[i],b[i]);
	}
}
void dfs(int x)
{
	ans+=char(x+'a'-1);
	u[x]=true;
	for(int i=0;i<v[x].size();i++)
		if(u[v[x][i]])
		{
			cout<<"Impossible";
			exit(0);
		}
		else
			dfs(v[x][i]);
}
int main(){
	cin>>n;
	cin>>s[1];
	for(int i=2;i<=n;i++)
	{
		cin>>s[i];
		order[i-1]=f(s[i-1],s[i]);
	}
	if(ans=="Impossible")
	{
		cout<<ans;
		return 0;
	}
	for(int i=1;i<n;i++)
	{
		x=order[i].first,y=order[i].second;
		if(x==y)
			continue;
		v[x-'a'+1].push_back(y-'a'+1);
	}
	start=1;
	while(order[start].first==order[start].second)
		start++;
	dfs(order[start].first-'a'+1);
	for(int i=1;i<=26;i++)
		if(!u[i])
			ans+=char(i+'a'-1);
	cout<<ans;
	return 0;
}


#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int inf=1e9,dx[]={-1,0,1,0},dy[]={0,-1,0,1};
const long long llinf=1e18;
int n,cnt,deep,start;
char x,y;
string s[105],ans;
pair<char,char> order[105];
vector<int> v[30];
int u[30];
bool ok,ok2;
pair<char,char> f(string a,string b)
{
	int i;
	if(a.size()==b.size())
	{
		for(i=0;a[i]==b[i];i++);
		return make_pair(a[i],b[i]);
	}
	else if(a.size()>b.size())
	{
		for(i=0;a[i]==b[i]&&i<b.size();i++);
		if(i==b.size())
		{
			ans="Impossible";
			return make_pair('|','|');
		}
		return make_pair(a[i],b[i]);
	}
	else
	{
		for(i=0;a[i]==b[i]&&i<a.size();i++);
		if(i==a.size())
			return make_pair('|','|');
		return make_pair(a[i],b[i]);
	}
}
void dfs(int x)
{
	ans+=char(x+'a'-1);
	u[x]=1;
	for(int i=0;i<v[x].size();i++)
		if(!u[v[x][i]])
			dfs(v[x][i]);
		else if(u[v[x][i]]==1)
		{
			cout<<"Impossible";
			exit(0);
		}
	u[x]=2;
}
int main(){
	cin>>n;
	cin>>s[1];
	for(int i=2;i<=n;i++)
	{
		cin>>s[i];
		order[i-1]=f(s[i-1],s[i]);
	}
	if(ans=="Impossible")
	{
		cout<<ans;
		return 0;
	}
	for(int i=1;i<n;i++)
	{
		x=order[i].first,y=order[i].second;
		if(x==y)
			continue;
		if(x>y)
			ok2=true;
		v[x-'a'+1].push_back(y-'a'+1);
		ok=true;
	}
	if(!ok||!ok2)
	{
		cout<<"abcdefghijklmnopqrstuvwxyz";
		return 0;
	}
	start=1;
	while(start<n)
	{
		if(order[start].first!=order[start].second&&!u[order[start].first-'a'+1])
			dfs(order[start].first-'a'+1);
		start++;
	}
	for(int i=1;i<=26;i++)
		if(!u[i])
			dfs(i);
	if(ans.size()!=26)
	{
		cout<<"Impossible";
		return 0;
	}
	cout<<ans;
	return 0;
}


#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int inf=1e9,dx[]={-1,0,1,0},dy[]={0,-1,0,1};
const long long llinf=1e18;
int n,cnt,deep,start;
char x,y;
string s[105],ans;
pair<char,char> order[105];
vector<int> v[30];
bool u[30],ok;
pair<char,char> f(string a,string b)
{
	int i;
	if(a.size()==b.size())
	{
		for(i=0;a[i]==b[i];i++);
		return make_pair(a[i],b[i]);
	}
	else if(a.size()>b.size())
	{
		for(i=0;a[i]==b[i]&&i<b.size();i++);
		if(i==b.size())
		{
			ans="Impossible";
			return make_pair('|','|');
		}
		return make_pair(a[i],b[i]);
	}
	else
	{
		for(i=0;a[i]==b[i]&&i<a.size();i++);
		if(i==a.size())
			return make_pair('|','|');
		return make_pair(a[i],b[i]);
	}
}
void dfs(int x)
{
	ans+=char(x+'a'-1);
	u[x]=true;
	for(int i=0;i<v[x].size();i++)
		if(u[v[x][i]])
		{
			cout<<"Impossible";
			exit(0);
		}
		else
			dfs(v[x][i]);
}
int main(){
	cin>>n;
	cin>>s[1];
	for(int i=2;i<=n;i++)
	{
		cin>>s[i];
		order[i-1]=f(s[i-1],s[i]);
	}
	if(ans=="Impossible")
	{
		cout<<ans;
		return 0;
	}
	for(int i=1;i<n;i++)
	{
		x=order[i].first,y=order[i].second;
		if(x==y)
			continue;
		v[x-'a'+1].push_back(y-'a'+1);
		ok=true;
	}
	if(!ok)
	{
		cout<<"abcdefghijklmnopqrstuvwxyz";
		return 0;
	}
	start=1;
	while(order[start].first==order[start].second)
		start++;
	dfs(order[start].first-'a'+1);
	for(int i=1;i<=26;i++)
		if(!u[i])
			ans+=char(i+'a'-1);
	cout<<ans;
	return 0;
}


#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int inf=1e9,dx[]={-1,0,1,0},dy[]={0,-1,0,1};
const long long llinf=1e18;
int n,cnt,deep,start;
char x,y;
string s[105],ans;
pair<char,char> order[105];
vector<int> v[30];
bool u[30],ok;
pair<char,char> f(string a,string b)
{
	int i;
	if(a.size()==b.size())
	{
		for(i=0;a[i]==b[i];i++);
		return make_pair(a[i],b[i]);
	}
	else if(a.size()>b.size())
	{
		for(i=0;a[i]==b[i]&&i<b.size();i++);
		if(i==b.size())
		{
			ans="Impossible";
			return make_pair('|','|');
		}
		return make_pair(a[i],b[i]);
	}
	else
	{
		for(i=0;a[i]==b[i]&&i<a.size();i++);
		if(i==a.size())
			return make_pair('|','|');
		return make_pair(a[i],b[i]);
	}
}
void dfs(int x,bool f)
{
	if(!f&&v[x].size()==0)
		return;
	ans+=char(x+'a'-1);
	u[x]=true;
	for(int i=0;i<v[x].size();i++)
	{
		if(u[v[x][i]])
		{
			cout<<"Impossible";
			exit(0);
		}
		else
			dfs(v[x][i],true);
	}
}
int main(){
	cin>>n;
	cin>>s[1];
	for(int i=2;i<=n;i++)
	{
		cin>>s[i];
		order[i-1]=f(s[i-1],s[i]);
	}
	if(ans=="Impossible")
	{
		cout<<ans;
		return 0;
	}
	for(int i=1;i<n;i++)
	{
		x=order[i].first,y=order[i].second;
		if(x==y)
			continue;
		v[x-'a'+1].push_back(y-'a'+1);
		ok=true;
	}
	if(!ok)
	{
		cout<<"abcdefghijklmnopqrstuvwxyz";
		return 0;
	}
	start=1;
	while(order[start].first==order[start].second)
		start++;
	for(int i=1;i<=26;i++)
		if(!u[i])
			dfs(i,false);
	for(int i=1;i<=26;i++)
		if(!u[i])
			ans+=char(i+'a'-1);
	cout<<ans;
	return 0;
}


#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <string>
using namespace std;

vector<int> g[26];

bool cycle;
vector<int> order;

int u[26];
void dfs(int v) {
    u[v] = 1;
    for (int i = 0; i < g[v].size(); i++) {
        int to = g[v][i];
        if (u[to] == 0) {
            dfs(to);
        } else if (u[to] == 1) {
            cycle = 1;
        }
    }
    u[v] = 2;
    order.push_back(v);
}

int main() {
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);

    int n;
    cin >> n;

    string s[110];
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }

    for (int i = 1; i < n; i++) {
        string &a = s[i - 1], &b = s[i];
        bool f = 0;
        for (int j = 0; j < min(a.size(), b.size()); j++) {
            if (a[j] != b[j]) {
                g[a[j] - 'a'].push_back(b[j] - 'a');
                f = 1;
                break;
            }
        }
        if (!f && a.size() > b.size()) {
            cout << "Impossible";
            return 0;
        }
    }

    for (int i = 0; i < 26; i++)
        if (!u[i])
            dfs(i);

    if (cycle) {
        cout << "Impossible";
        return 0;
    }

    for (int i = 25; i >= 0; i--)
        cout << (char)('a' + order[i]);
}


#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <vector>
#include <climits>
#include <set>
#include <algorithm>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <stack>
#include <string>
#include <queue>
#define pii pair<int,int>
#define pll pair<long long, long long>
#define f first
#define sum(x) ((x)*((x)+1)/2)
#define abs(x) (((x)<0 ? -(x) : (x)))
#define min(x,y) (((x) < (y)) ? (x) : (y))
#define max(x,y) (((x) > (y)) ? (x) : (y))
#define mkp make_pair
#define pb push_back
#define printArray(x) {for(int prt=0;prt<N;prt++){cout << x[prt] << ',';} cout << endl;}
#define rep(i,a,b) for(int i=a;i<b;i++)
#define repb(i,a,b) for(int i=a;i>=b;i--)
typedef unsigned long long ll;

int MOD = 1e9 + 7;
using namespace std;
ll add(ll a, ll b) {
    ll res = a + b;

    while (res >= MOD) res -= MOD;

    while (res < 0) res += MOD;

    return res;
}

ll mul(ll a, ll b){
    ll res = a * b;

    while (res >= MOD) res -= MOD;

    while (res < 0) res += MOD;

    return res;
}

int main(){
#ifdef ULAZ
    freopen("in.in", "r", stdin);
    //freopen("out.out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    int n;
    cin >> n;
    vector<string> s(n);
    getline(cin, s[0]);
    for (int i = 0; i < n; i++){
        getline(cin,s[i]);
    }
    vector<vector<int>> alph(26, vector<int>());
    vector<vector<int>> alph2(26, vector<int>()); //reverse edges
    int totalEdges = 0;
    for (int i = 0; i+1 < n; i++){
        //get the first two chars that differ (if there are no such chars => check which one is prefix of which one)
        int differ = -1;
        for (int j = 0; j < min(s[i].size(), s[i + 1].size());j++){
            if (s[i][j] != s[i + 1][j]){
                differ = j;
                break;
            }
        }
        if (differ == -1){
            if (s[i].size() < s[i + 1].size()){
                continue;
            }
            else{
                cout << "Impossible" << endl;
            }
        }
        //add edge to graph
        alph[s[i][differ] - 'a'].push_back(s[i+1][differ] - 'a');
        alph2[s[i+1][differ]-'a'].push_back(s[i][differ] - 'a');
        totalEdges++;
    }
    //Now try to find order (TOPO-Sort)
    stack<int> freeNodes;
    queue<char> ordering;
    vector<bool> pushed(26,false);
    for (int i = 0; i < 26; i++){
        if (alph2[i].empty()){
            freeNodes.push(i);
        }
    }
    while (!freeNodes.empty()){
        int n = freeNodes.top();
        freeNodes.pop();
        ordering.push(n + 'a');
        //Delete edges from n to other nodes
        for (int j = 0; j < alph[n].size(); j++){
            for (int k = 0; k < alph2[alph[n][j]].size(); k++){
                if (alph2[alph[n][j]][k] == n){
                    alph2[alph[n][j]][k] = -1;
                    totalEdges--;
                }
            }
            int cnt = 0;
            for (int k = 0; k < alph2[alph[n][j]].size(); k++){
                if (alph2[alph[n][j]][k] != -1){
                    cnt++;
                }
            }
            if (cnt == 0 && !pushed[alph[n][j]]){
                freeNodes.push(alph[n][j]);
                pushed[alph[n][j]] = true;
            }
        }
    }
    if (totalEdges){
        cout << "Impossible" << endl;
        return 0;
    }
    while (!ordering.empty()){
        cout << ordering.front();
        ordering.pop();
    }
    cout << endl;
#ifdef ULAZ
    while (1);
#endif
}


#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <vector>
#include <climits>
#include <set>
#include <algorithm>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <stack>
#include <string>
#include <queue>
#define pii pair<int,int>
#define pll pair<long long, long long>
#define f first
#define sum(x) ((x)*((x)+1)/2)
#define abs(x) (((x)<0 ? -(x) : (x)))
#define min(x,y) (((x) < (y)) ? (x) : (y))
#define max(x,y) (((x) > (y)) ? (x) : (y))
#define mkp make_pair
#define pb push_back
#define printArray(x) {for(int prt=0;prt<N;prt++){cout << x[prt] << ',';} cout << endl;}
#define rep(i,a,b) for(int i=a;i<b;i++)
#define repb(i,a,b) for(int i=a;i>=b;i--)
typedef unsigned long long ll;

int MOD = 1e9 + 7;
using namespace std;
ll add(ll a, ll b) {
    ll res = a + b;

    while (res >= MOD) res -= MOD;

    while (res < 0) res += MOD;

    return res;
}

ll mul(ll a, ll b){
    ll res = a * b;

    while (res >= MOD) res -= MOD;

    while (res < 0) res += MOD;

    return res;
}

int main(){
#ifdef ULAZ
    freopen("in.in", "r", stdin);
    //freopen("out.out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    int n;
    cin >> n;
    vector<string> s(n);
    getline(cin, s[0]);
    for (int i = 0; i < n; i++){
        getline(cin,s[i]);
    }
    vector<vector<int>> alph(26, vector<int>());
    vector<vector<int>> alph2(26, vector<int>()); //reverse edges
    int totalEdges = 0;
    for (int i = 0; i+1 < n; i++){
        //get the first two chars that differ (if there are no such chars => check which one is prefix of which one)
        int differ = -1;
        for (int j = 0; j < min(s[i].size(), s[i + 1].size());j++){
            if (s[i][j] != s[i + 1][j]){
                differ = j;
                break;
            }
        }
        if (differ == -1){
            if (s[i].size() < s[i + 1].size()){
                continue;
            }
            else{
                cout << "Impossible" << endl; return 0;
            }
        }
        //add edge to graph
        alph[s[i][differ] - 'a'].push_back(s[i+1][differ] - 'a');
        alph2[s[i+1][differ]-'a'].push_back(s[i][differ] - 'a');
        totalEdges++;
    }
    //Now try to find order (TOPO-Sort)
    stack<int> freeNodes;
    queue<char> ordering;
    vector<bool> pushed(26,false);
    for (int i = 0; i < 26; i++){
        if (alph2[i].empty()){
            freeNodes.push(i);
        }
    }
    while (!freeNodes.empty()){
        int n = freeNodes.top();
        freeNodes.pop();
        ordering.push(n + 'a');
        //Delete edges from n to other nodes
        for (int j = 0; j < alph[n].size(); j++){
            for (int k = 0; k < alph2[alph[n][j]].size(); k++){
                if (alph2[alph[n][j]][k] == n){
                    alph2[alph[n][j]][k] = -1;
                    totalEdges--;
                }
            }
            int cnt = 0;
            for (int k = 0; k < alph2[alph[n][j]].size(); k++){
                if (alph2[alph[n][j]][k] != -1){
                    cnt++;
                }
            }
            if (cnt == 0 && !pushed[alph[n][j]]){
                freeNodes.push(alph[n][j]);
                pushed[alph[n][j]] = true;
            }
        }
    }
    if (totalEdges){
        cout << "Impossible" << endl;
        return 0;
    }
    while (!ordering.empty()){
        cout << ordering.front();
        ordering.pop();
    }
    cout << endl;
#ifdef ULAZ
    while (1);
#endif
}


#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <vector>
#include <climits>
#include <set>
#include <algorithm>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <stack>
#include <string>
#include <queue>
#define pii pair<int,int>
#define pll pair<long long, long long>
#define f first
#define sum(x) ((x)*((x)+1)/2)
#define abs(x) (((x)<0 ? -(x) : (x)))
#define min(x,y) (((x) < (y)) ? (x) : (y))
#define max(x,y) (((x) > (y)) ? (x) : (y))
#define mkp make_pair
#define pb push_back
#define printArray(x) {for(int prt=0;prt<N;prt++){cout << x[prt] << ',';} cout << endl;}
#define rep(i,a,b) for(int i=a;i<b;i++)
#define repb(i,a,b) for(int i=a;i>=b;i--)
typedef unsigned long long ll;

int MOD = 1e9 + 7;
using namespace std;
ll add(ll a, ll b) {
    ll res = a + b;

    while (res >= MOD) res -= MOD;

    while (res < 0) res += MOD;

    return res;
}

ll mul(ll a, ll b){
    ll res = a * b;

    while (res >= MOD) res -= MOD;

    while (res < 0) res += MOD;

    return res;
}

int main(){
#ifdef ULAZ
    freopen("in.in", "r", stdin);
    //freopen("out.out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    int n;
    cin >> n;
    vector<string> s(n);
    getline(cin, s[0]);
    for (int i = 0; i < n; i++){
        getline(cin,s[i]);
    }
    vector<vector<int>> alph(26, vector<int>());
    vector<vector<int>> alph2(26, vector<int>()); //reverse edges
    int totalEdges = 0;
    for (int i = 0; i+1 < n; i++){
        //get the first two chars that differ (if there are no such chars => check which one is prefix of which one)
        int differ = -1;
        for (int j = 0; j < min(s[i].size(), s[i + 1].size());j++){
            if (s[i][j] != s[i + 1][j]){
                differ = j;
                break;
            }
        }
        if (differ == -1){
            if (s[i].size() < s[i + 1].size()){
                continue;
            }
            else{
                cout << "Impossible" << endl;
            }
        }
        //add edge to graph
        alph[s[i][differ] - 'a'].push_back(s[i+1][differ] - 'a');
        alph2[s[i+1][differ]-'a'].push_back(s[i][differ] - 'a');
        totalEdges++;
    }
    //Now try to find order (TOPO-Sort)
    stack<int> freeNodes;
    queue<char> ordering;
    for (int i = 0; i < 26; i++){
        if (alph2[i].empty()){
            freeNodes.push(i);
        }
    }
    while (!freeNodes.empty()){
        int n = freeNodes.top();
        freeNodes.pop();
        ordering.push(n + 'a');
        //Delete edges from n to other nodes
        for (int j = 0; j < alph[n].size(); j++){
            for (int k = 0; k < alph2[alph[n][j]].size(); k++){
                if (alph2[alph[n][j]][k] == n){
                    alph2[alph[n][j]][k] = -1;
                    totalEdges--;
                }
            }
            int cnt = 0;
            for (int k = 0; k < alph2[alph[n][j]].size(); k++){
                if (alph2[alph[n][j]][k] != -1){
                    cnt++;
                }
            }
            if (cnt == 0){
                freeNodes.push(alph[n][j]);
            }
        }
    }
    if (totalEdges){
        cout << "Impossible" << endl;
        return 0;
    }
    while (!ordering.empty()){
        cout << ordering.front();
        ordering.pop();
    }
    cout << endl;
#ifdef ULAZ
    while (1);
#endif
}


#define _USE_MATH_DEFINES
#pragma comment(linker, "/STACK:167772016")

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <bitset>
#include <algorithm>
#include <ctime>
#include <cassert>
#include <cmath>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define pb push_back
#define mp make_pair
#define all(a) a.begin(),a.end()

typedef long long li;
typedef double ld;

typedef pair<int,int> pt;
#define ft first
#define sc second

const int INF = int(1e9) + 6;
const li INF64 = li(1e18);
const ld EPS = 1e-9;

#define sqr(n) ((n) * (n))

int n;
const int N = 1000;
string s[N];

bool read()
{
    cin >> n;
    forn (i, n)
        cin >> s[i];
    return true;
}

vector<int> g[50];

vector<int> x;
bool used[50];

void dfs(int v)
{
    if (used[v])
        return;
    used[v] = true;
    forn (i, g[v].size())
        dfs(g[v][i]);
    x.pb(v);
}

void solve()
{
    forn (i, n - 1)
    {
        forn (j, min(s[i].size(), s[i + 1].size()))
            if (s[i][j] != s[i + 1][j])
            {
                g[s[i + 1][j] - 'a'].pb(s[i][j] - 'a');
                break;
            }
    }

    forn (i, 26)
        dfs(i);

    int pos[26];
    forn (i, 26)
        pos[x[i]] = i;

    forn (i, n)
        forn (j, s[i].size())
            s[i][j] = pos[s[i][j] - 'a'] + 'a';

    forn (i, n - 1)
    {
        if (s[i] > s[i + 1])
        {
            cout << "Impossible" << endl;
            return;
        }
    }

    forn (i, 26)
        cout << char(x[i] + 'a');
    cout << endl;
}

int main()
{

#ifdef _DEBUG
    freopen("input.txt", "r", stdin);
//  freopen("output.txt", "w", stdout);
#endif

    read();
    solve();

    return 0;
}


#define _USE_MATH_DEFINES
#pragma comment(linker, "/STACK:167772016")

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <bitset>
#include <algorithm>
#include <ctime>
#include <cassert>
#include <cmath>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define pb push_back
#define mp make_pair
#define all(a) a.begin(),a.end()

typedef long long li;
typedef double ld;

typedef pair<int,int> pt;
#define ft first
#define sc second

const int INF = int(1e9) + 6;
const li INF64 = li(1e18);
const ld EPS = 1e-9;

#define sqr(n) ((n) * (n))

int n;
const int N = 1000;
string s[N];

bool read()
{
    cin >> n;
    forn (i, n)
        cin >> s[i];
    return true;
}

vector<int> g[50];

vector<int> x;
bool used[50];

void dfs(int v)
{
    if (used[v])
        return;
    used[v] = true;
    forn (i, g[v].size())
        dfs(g[v][i]);
    x.pb(v);
}

void solve()
{
    forn (i, n - 1)
    {
        forn (j, min(s[i].size(), s[i + 1].size()))
            if (s[i][j] != s[i + 1][j])
            {
                g[s[i + 1][j] - 'a'].pb(s[i][j] - 'a');
                break;
            }
    }

    forn (i, 26)
        dfs(i);

    int ft = 0;
    map<char, char> f;

    forn (j, 100)
        forn (i, n)
        {
            if (s[i].size() <= j)
                continue;
            if (f.count(s[i][j]) == 0)
                f[s[i][j]] = char(ft++ + 'a');
            s[i][j] = f[s[i][j]];
        }

    forn (i, n - 1)
    {
        if (s[i] > s[i + 1])
        {
            cout << "Impossible" << endl;
            return;
        }
    }

    forn (i, 26)
        cout << char(x[i] + 'a');
    cout << endl;
}

int main()
{

#ifdef _DEBUG
    freopen("input.txt", "r", stdin);
//  freopen("output.txt", "w", stdout);
#endif

    read();
    solve();

    return 0;
}


//#pragma comment(linker,"/STACK:16777216") /*16Mb*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <cmath>
#include <list>
#include <iomanip>
#include <set>
#include <map>
#include <sstream>
#include <fstream>
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef vector<int> VI;

#define FOR(i,a,b) for(int (i)=(a);i<(b);++(i))
#define RFOR(i,a,b) for(int (i)=(a)-1;(i)>=(b);--(i))
#define For(i,a,b) for(int (i)=(a);i<(b);++(i))
#define FoR(i,a,b) for(int (i)=(a)-1;(i)>=(b);--(i))
#define MP make_pair
#define I insert
#define mod 1000000007
#define INF 1000000001
#define PB push_back
#define x0 sdfhrthrth
#define x1 fdhttrlhn
#define y0 kihrbdb
#define y1 ugvrrtgtrg
#define eps 1e-5
#define X first
#define Y second

int m;
string a[100000];
int g[50][50];
vector<int> now;

void main()
{
	cin>>m;
	For(i,0,m) cin>>a[i];
	For(i,0,m-1)
	{
		int j=0;
		while (a[i].size()>j && a[i+1].size()>j && a[i][j]==a[i+1][j]) j++;
		if (a[i].size()>j && a[i+1].size()>j)
			g[a[i+1][j]-'a'][a[i][j]-'a']=1;
	}
	string ans="";
	For(i,0,'z'-'a'+1)
	{
		bool ok=0;
		For(j,0,50)
			if (g[i][j]) ok=1;
		if (!ok)
		{
			ans+=char('a'+i);
			now.PB(i);
		}
	}
	while (now.size())
	{
		int Q=now[now.size()-1];
		now.pop_back();
		For(i,0,50)
			if (g[i][Q]==1)
			{
				g[i][Q]=0;
				bool ok=0;
				For(t,0,50)
					if (g[i][t]) ok=1;
				if (!ok)
				{
					ans+=char('a'+i);
					now.PB(i);
				}
			}
	}
	if (ans.size()=='z'-'a'+1)
		cout<<ans;
	else cout<<"Impossible";

}