#include <bits/stdc++.h>
#define int long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
int par[LIM][LIM];
vector<pii> adj[LIM];

int dfs(int nd,int ct)
{
	if(ct<0)
	{
		return INT_MAX;
	}
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	if(nd==0)
	{
		if(ct>0)
			return INT_MAX;
		dp[nd][ct] = 0;
		return 0;
	}
	int dis = INT_MAX;
	int nnn = -1;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct-1);
		if(curr==INT_MAX)
			continue;

		curr+=edge.S;
		if(curr<dis)
		{
			dis = curr;
			nnn = edge.F;
		}
	}
	//visited[nd] = false;
	par[nd][ct] = nnn;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	memset(par,-1,sizeof(int)*LIM*LIM);
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		adj[v].pb(mp(u,w));
	}
	REPD(i,n)
	{
		//print(dp[n-1][i]);
		int holy = dfs(n-1,i);
		//debug2(holy,i);
		if(holy<=T)
		{
			vi v;
			int nd,ct;
			nd = n-1,ct = i;
			while(nd!=0)
			{
				v.pb(nd+1);
				nd = par[nd][ct--];
			}
			v.pb(1);
			reverse(all(v));
			print(v.size());
			for(int x : v)
				cout << x << " ";
			cout << "\n";
			return;
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
map<pii,int> par;
map<pii,int> cost;
vector<bool> visited;
vector<pii> adj[LIM];

int dfs(int nd,int ct,int pr)
{
	if(visited[nd])
		return -1;
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	par.insert(mp(mp(nd,ct),pr));
	if(nd==0)
	{
		dp[nd][ct] = 0;
		return 0;
	}
	visited[nd] = true;
	int dis = INT_MAX;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct+1,nd)+edge.S;
		if(curr<dis)
		{
			dis = curr;
		}
	}
	visited[nd] = false;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	cost.clear();
	par.clear();
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		cost.insert(mp(mp(u,v),w));
		adj[v].pb(mp(u,w));
	}
	//REP(i,n) REP(j,n) print(cost[i][j]);
	visited.clear();
	REP(i,n) visited.pb(false);
	dfs(n-1,0,-1);

	/*
	//Iterative DFS
	struct node{int nd;int ct;int pr;};
	stack<node> stck;
	stck.push({n-1,0,-1});
	while(!stck.empty())
	{
		node x = stck.top();
		if(dp[x.nd][x.ct]!=-1)
		{
			//debug("Happy New Year");
			stck.pop();
			continue;
		}
		//par[x.nd][x.ct] = x.pr;
		par.insert(mp(mp(x.nd,x.ct),x.pr));
		if(x.nd==0)
		{
			dp[x.nd][x.ct] = 0;
			stck.pop();
			continue;
		}
		visited[x.nd] = true;
		int dis = INT_MAX;
		bool ok = true;
		if(x.nd==n-1)
		{
			int xx = 0;
		}
		for(pii edge : adj[x.nd])
		{
			if(visited[edge.F])
				continue;
			if(dp[edge.F][x.ct+1]==-1)
			{
				ok = false;
				stck.push({edge.F,x.ct+1,x.nd});
				break;
			}
			int curr = dp[edge.F][x.ct+1]+edge.S;
			if(curr<dis)
			{
				dis = curr;
			}
		}
		if(!ok) continue;
		visited[x.nd] = false;
		dp[x.nd][x.ct] = dis;
		stck.pop();
	}
	//End of Iterative DFS
	*/

	REPD(i,n)
	{
		//print(dp[n-1][i]);
		if(dp[0][i]!=-1)
		{
			vi v;
			int nd,ct;
			nd = 0;
			ct = i;
			bool ex = true;
			int sum = 0;
			while(nd!=-1)
			{
				v.pb(nd+1);
				if(sum>T)
				{
					if(i==152)
					{
						throw invalid_argument("CJ_DIES");
					}
					ex = false;
					//debug3(sum,nd,"HOLA:()");
					break;
				}
				int pp = par[mp(nd,ct--)];
				sum+=cost[mp(nd,pp)];
				nd = pp;
			}
			if(ex)
			{
				//print(tt);
				print(v.size());
				for(int x : v)
					cout << x << " ";
				cout << "\n";
				return;
			}
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
map<pii,int> par;
map<pii,int> cost;
vector<bool> visited;
vector<pii> adj[LIM];

int dfs(int nd,int ct,int pr)
{
	if(visited[nd])
		return -1;
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	par.insert(mp(mp(nd,ct),pr));
	if(nd==0)
	{
		dp[nd][ct] = 0;
		return 0;
	}
	visited[nd] = true;
	int dis = INT_MAX;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct+1,nd)+edge.S;
		if(curr<dis)
		{
			dis = curr;
		}
	}
	visited[nd] = false;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	cost.clear();
	par.clear();
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		cost.insert(mp(mp(u,v),w));
		adj[v].pb(mp(u,w));
	}
	//REP(i,n) REP(j,n) print(cost[i][j]);
	visited.clear();
	REP(i,n) visited.pb(false);
	dfs(n-1,0,-1);

	/*
	//Iterative DFS
	struct node{int nd;int ct;int pr;};
	stack<node> stck;
	stck.push({n-1,0,-1});
	while(!stck.empty())
	{
		node x = stck.top();
		if(dp[x.nd][x.ct]!=-1)
		{
			//debug("Happy New Year");
			stck.pop();
			continue;
		}
		//par[x.nd][x.ct] = x.pr;
		par.insert(mp(mp(x.nd,x.ct),x.pr));
		if(x.nd==0)
		{
			dp[x.nd][x.ct] = 0;
			stck.pop();
			continue;
		}
		visited[x.nd] = true;
		int dis = INT_MAX;
		bool ok = true;
		if(x.nd==n-1)
		{
			int xx = 0;
		}
		for(pii edge : adj[x.nd])
		{
			if(visited[edge.F])
				continue;
			if(dp[edge.F][x.ct+1]==-1)
			{
				ok = false;
				stck.push({edge.F,x.ct+1,x.nd});
				break;
			}
			int curr = dp[edge.F][x.ct+1]+edge.S;
			if(curr<dis)
			{
				dis = curr;
			}
		}
		if(!ok) continue;
		visited[x.nd] = false;
		dp[x.nd][x.ct] = dis;
		stck.pop();
	}
	//End of Iterative DFS
	*/

	REPD(i,n)
	{
		//print(dp[n-1][i]);
		if(dp[0][i]!=-1)
		{
			vi v;
			int nd,ct;
			nd = 0;
			ct = i;
			bool ex = true;
			int sum = 0;
			while(nd!=-1)
			{
				v.pb(nd+1);
				if(sum>T)
				{
					ex = false;
					//debug3(sum,nd,"HOLA:()");
					break;
				}
				int pp = par[mp(nd,ct--)];
				int cc = cost[mp(nd,pp)];
				if(pp>INF||pp==-1)
				{
					throw invalid_argument("CHOUD");
				}
				sum+=cc;
				nd = pp;
			}
			if(ex)
			{
				//print(tt);
				print(v.size());
				for(int x : v)
					cout << x << " ";
				cout << "\n";
				return;
			}
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 6/*5000+5*/;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
vector<pii> adj[LIM];
int dp[LIM][LIM];
int par[LIM][LIM];
int cost[LIM][LIM];

vi nll = {-1};
vector<bool> visited;

int dfs(int nd,int ct,int pr)
{
	if(visited[nd])
		return -1;
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	par[nd][ct] = pr;
	if(nd==0)
	{
		dp[nd][ct] = 0;
		return 0;
	}
	visited[nd] = true;
	int dis = INT_MAX;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct+1,nd)+edge.S;
		if(curr<dis)
		{
			dis = curr;
		}
	}
	visited[nd] = false;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	memset(par,-1,sizeof(int)*LIM*LIM);
	memset(cost,-1,sizeof(int)*LIM*LIM);
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		cost[u][v] = w;
		adj[v].pb(mp(u,w));
	}
	//REP(i,n) REP(j,n) print(cost[i][j]);
	visited.clear();
	REP(i,n) visited.pb(false);
	// dfs(n-1,0,-1);

	//Iterative DFS
	struct node{int nd;int ct;int pr;};
	stack<node> stck;
	stck.push({n-1,0,-1});
	while(!stck.empty())
	{
		node x = stck.top();
		if(dp[x.nd][x.ct]!=-1)
		{
			//debug("Happy New Year");
			stck.pop();
			continue;
		}
		par[x.nd][x.ct] = x.pr;
		if(x.nd==0)
		{
			dp[x.nd][x.ct] = 0;
			stck.pop();
			continue;
		}
		visited[x.nd] = true;
		int dis = INT_MAX;
		bool ok = true;
		if(x.nd==n-1)
		{
			int xx = 0;
		}
		for(pii edge : adj[x.nd])
		{
			if(visited[edge.F])
				continue;
			if(dp[edge.F][x.ct+1]==-1)
			{
				ok = false;
				stck.push({edge.F,x.ct+1,x.nd});
				break;
			}
			int curr = dp[edge.F][x.ct+1]+edge.S;
			if(curr<dis)
			{
				dis = curr;
			}
		}
		if(!ok) continue;
		visited[x.nd] = false;
		dp[x.nd][x.ct] = dis;
		stck.pop();
	}
	//End of Iterative DFS

	REPD(i,n)
	{
		//print(dp[n-1][i]);
		if(dp[0][i]!=-1)
		{
			vi v;
			int nd,ct;
			nd = 0;
			ct = i;
			bool ex = true;
			int sum = 0;
			while(nd!=-1)
			{
				v.pb(nd+1);
				if(sum>T)
				{
					ex = false;
					//debug3(sum,nd,"HOLA:()");
					break;
				}
				int pp = par[nd][ct--];
				sum+=cost[nd][pp];
				nd = pp;
			}
			if(ex)
			{
				//print(tt);
				print(v.size());
				for(int x : v)
					cout << x << " ";
				cout << "\n";
				return;
			}
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
vector<pii> adj[LIM];
int dp[LIM][LIM];
int par[LIM][LIM];
int cost[LIM][LIM];

vi nll = {-1};
vector<bool> visited;

int dfs(int nd,int ct,int pr)
{
	if(visited[nd])
		return -1;
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	par[nd][ct] = pr;
	if(nd==0)
	{
		dp[nd][ct] = 0;
		return 0;
	}
	visited[nd] = true;
	int dis = INT_MAX;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct+1,nd)+edge.S;
		if(curr<dis)
		{
			dis = curr;
		}
	}
	visited[nd] = false;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	memset(par,-1,sizeof(int)*LIM*LIM);
	memset(cost,-1,sizeof(int)*LIM*LIM);
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		cost[u][v] = w;
		adj[v].pb(mp(u,w));
	}
	//REP(i,n) REP(j,n) print(cost[i][j]);
	visited.clear();
	REP(i,n) visited.pb(false);
	dfs(n-1,0,-1);
	REPD(i,n)
	{
		//print(dp[n-1][i]);
		if(dp[0][i]!=-1)
		{
			vi v;
			int nd,ct;
			nd = 0;
			ct = i;
			bool ex = true;
			int sum = 0;
			while(nd!=-1)
			{
				v.pb(nd+1);
				if(sum>T)
				{
					ex = false;
					//debug3(sum,nd,"HOLA:()");
					break;
				}
				int pp = par[nd][ct--];
				sum+=cost[nd][pp];
				nd = pp;
			}
			if(ex)
			{
				//print(tt);
				print(v.size());
				for(int x : v)
					cout << x << " ";
				cout << "\n";
				return;
			}
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
int par[LIM][LIM];
vector<pii> adj[LIM];

int dfs(int nd,int ct)
{
	if(ct<0)
	{
		return INF;
	}
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	if(nd==0)
	{
		if(ct>0)
			return INF;
		dp[nd][ct] = 0;
		return 0;
	}
	int dis = INF;
	int nnn = -1;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct-1);
		if(curr==INT_MAX)
			continue;

		curr+=edge.S;
		if(curr<dis)
		{
			dis = curr;
			nnn = edge.F;
		}
	}
	//visited[nd] = false;
	par[nd][ct] = nnn;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	memset(par,-1,sizeof(int)*LIM*LIM);
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		adj[v].pb(mp(u,w));
	}
	REPD(i,n)
	{
		//print(dp[n-1][i]);
		int holy = dfs(n-1,i);
		//debug2(holy,i);
		if(holy<=T)
		{
			vi v;
			int nd,ct;
			nd = n-1,ct = i;
			while(nd!=0)
			{
				v.pb(nd+1);
				nd = par[nd][ct--];
			}
			v.pb(1);
			reverse(all(v));
			print(v.size());
			for(int x : v)
				cout << x << " ";
			cout << "\n";
			return;
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
map<pii,int> par;
map<pii,int> cost;
vector<bool> visited;
vector<pii> adj[LIM];

int dfs(int nd,int ct,int pr)
{
	if(visited[nd])
		return -1;
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	par.insert(mp(mp(nd,ct),pr));
	if(nd==0)
	{
		dp[nd][ct] = 0;
		return 0;
	}
	visited[nd] = true;
	int dis = INT_MAX;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct+1,nd)+edge.S;
		if(curr<dis)
		{
			dis = curr;
		}
	}
	visited[nd] = false;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	cost.clear();
	par.clear();
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		cost.insert(mp(mp(u,v),w));
		adj[v].pb(mp(u,w));
	}
	//REP(i,n) REP(j,n) print(cost[i][j]);
	visited.clear();
	REP(i,n) visited.pb(false);
	dfs(n-1,0,-1);

	/*
	//Iterative DFS
	struct node{int nd;int ct;int pr;};
	stack<node> stck;
	stck.push({n-1,0,-1});
	while(!stck.empty())
	{
		node x = stck.top();
		if(dp[x.nd][x.ct]!=-1)
		{
			//debug("Happy New Year");
			stck.pop();
			continue;
		}
		//par[x.nd][x.ct] = x.pr;
		par.insert(mp(mp(x.nd,x.ct),x.pr));
		if(x.nd==0)
		{
			dp[x.nd][x.ct] = 0;
			stck.pop();
			continue;
		}
		visited[x.nd] = true;
		int dis = INT_MAX;
		bool ok = true;
		if(x.nd==n-1)
		{
			int xx = 0;
		}
		for(pii edge : adj[x.nd])
		{
			if(visited[edge.F])
				continue;
			if(dp[edge.F][x.ct+1]==-1)
			{
				ok = false;
				stck.push({edge.F,x.ct+1,x.nd});
				break;
			}
			int curr = dp[edge.F][x.ct+1]+edge.S;
			if(curr<dis)
			{
				dis = curr;
			}
		}
		if(!ok) continue;
		visited[x.nd] = false;
		dp[x.nd][x.ct] = dis;
		stck.pop();
	}
	//End of Iterative DFS
	*/

	REPD(i,n)
	{
		//print(dp[n-1][i]);
		if(dp[0][i]!=-1)
		{
			vi v;
			int nd,ct;
			nd = 0;
			ct = i;
			bool ex = true;
			int sum = 0;
			while(nd!=-1)
			{
				v.pb(nd+1);
				if(sum>T)
				{
					ex = false;
					//debug3(sum,nd,"HOLA:()");
					break;
				}
				int pp = par[mp(nd,ct--)];
				sum+=cost[mp(nd,pp)];
				nd = pp;
			}
			if(ex)
			{
				//print(tt);
				print(v.size());
				for(int x : v)
					cout << x << " ";
				cout << "\n";
				return;
			}
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
map<pii,int> par;
map<pii,int> cost;
vector<pii> adj[LIM];

int dfs(int nd,int ct)
{
	if(ct<0)
	{
		return INT_MAX;
	}
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	if(nd==0)
	{
		if(ct>0)
			return INT_MAX;
		dp[nd][ct] = 0;
		return 0;
	}
	int dis = INT_MAX;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct-1);
		if(curr==INT_MAX)
			continue;
		curr+=edge.S;
		if(curr<dis)
		{
			dis = curr;
			par.insert(mp(mp(edge.F,ct-1),nd));
		}
	}
	//visited[nd] = false;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	cost.clear();
	par.clear();
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		cost.insert(mp(mp(u,v),w));
		adj[v].pb(mp(u,w));
	}
	REPD(i,n)
	{
		//print(dp[n-1][i]);
		int holy = 0;
		if(holy=dfs(n-1,i)<=T)
		{
			//print(holy);
			vi v;
			int nd,ct;
			nd = 0,ct = 0;
			while(nd!=(n-1))
			{
				v.pb(nd+1);
				nd = par[mp(nd,ct++)];
			}
			v.pb(n);
			print(v.size());
			for(int x : v)
				cout << x << " ";
			cout << "\n";
			return;
		}
		else
		{
			memset(dp,-1,sizeof(int)*LIM*LIM);
			par.clear();
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
vector<pii> adj[LIM];
int dp[LIM][LIM];
int par[LIM][LIM];
//int cost[LIM][LIM];

vi nll = {-1};
vector<bool> visited;

int dfs(int nd,int ct,int pr)
{
	if(visited[nd])
		return -1;
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	par[nd][ct] = pr;
	if(nd==0)
	{
		dp[nd][ct] = 0;
		return 0;
	}
	visited[nd] = true;
	int dis = INT_MAX;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct+1,nd)+edge.S;
		if(curr<dis)
		{
			dis = curr;
		}
	}
	visited[nd] = false;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	memset(par,-1,sizeof(int)*LIM*LIM);
	//memset(cost,-1,sizeof(int)*LIM*LIM);
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		//cost[u][v] = w;
		adj[v].pb(mp(u,w));
	}
	//REP(i,n) REP(j,n) print(cost[i][j]);
	visited.clear();
	REP(i,n) visited.pb(false);
	dfs(n-1,0,-1);
	REPD(i,n)
	{
		//print(dp[n-1][i]);
		if(dp[0][i]!=-1)
		{
			vi v;
			int nd,ct;
			nd = 0;
			ct = i;
			bool ex = true;
			int sum = 0;
			while(nd!=-1)
			{
				v.pb(nd+1);
				if(dp[nd][ct]>T)
				{
					ex = false;
					//debug3(sum,nd,"HOLA:()");
					break;
				}
				int pp = par[nd][ct--];
				//sum+=cost[nd][pp];
				nd = pp;
			}
			if(ex)
			{
				//print(tt);
				print(v.size());
				for(int x : v)
					cout << x << " ";
				cout << "\n";
				return;
			}
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
map<pii,int> par;
map<pii,int> cost;
vector<bool> visited;
vector<pii> adj[LIM];

int dfs(int nd,int ct,int pr)
{
	if(visited[nd])
		return -1;
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	par.insert(mp(mp(nd,ct),pr));
	if(nd==0)
	{
		dp[nd][ct] = 0;
		return 0;
	}
	visited[nd] = true;
	int dis = INT_MAX;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct+1,nd)+edge.S;
		if(curr<dis)
		{
			dis = curr;
		}
	}
	visited[nd] = false;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	cost.clear();
	par.clear();
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		cost.insert(mp(mp(u,v),w));
		adj[v].pb(mp(u,w));
	}
	//REP(i,n) REP(j,n) print(cost[i][j]);
	visited.clear();
	REP(i,n) visited.pb(false);
	dfs(n-1,0,-1);

	/*
	//Iterative DFS
	struct node{int nd;int ct;int pr;};
	stack<node> stck;
	stck.push({n-1,0,-1});
	while(!stck.empty())
	{
		node x = stck.top();
		if(dp[x.nd][x.ct]!=-1)
		{
			//debug("Happy New Year");
			stck.pop();
			continue;
		}
		//par[x.nd][x.ct] = x.pr;
		par.insert(mp(mp(x.nd,x.ct),x.pr));
		if(x.nd==0)
		{
			dp[x.nd][x.ct] = 0;
			stck.pop();
			continue;
		}
		visited[x.nd] = true;
		int dis = INT_MAX;
		bool ok = true;
		if(x.nd==n-1)
		{
			int xx = 0;
		}
		for(pii edge : adj[x.nd])
		{
			if(visited[edge.F])
				continue;
			if(dp[edge.F][x.ct+1]==-1)
			{
				ok = false;
				stck.push({edge.F,x.ct+1,x.nd});
				break;
			}
			int curr = dp[edge.F][x.ct+1]+edge.S;
			if(curr<dis)
			{
				dis = curr;
			}
		}
		if(!ok) continue;
		visited[x.nd] = false;
		dp[x.nd][x.ct] = dis;
		stck.pop();
	}
	//End of Iterative DFS
	*/

	REPD(i,n)
	{
		//print(dp[n-1][i]);
		if(dp[0][i]!=-1)
		{
			vi v;
			int nd,ct;
			nd = 0;
			ct = i;
			bool ex = true;
			int sum = 0;
			while(nd!=-1)
			{
				v.pb(nd+1);
				if(sum>T)
				{
					ex = false;
					//debug3(sum,nd,"HOLA:()");
					break;
				}
				int pp = par[mp(nd,ct--)];
				int cc = cost[mp(nd,pp)];
				sum+=cc;
				if(cc==-1)
				{
					throw invalid_argument("CHODU");
				}
				nd = pp;
			}
			if(ex)
			{
				//print(tt);
				print(v.size());
				for(int x : v)
					cout << x << " ";
				cout << "\n";
				return;
			}
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
map<pii,int> par;
map<pii,int> cost;
//vector<bool> visited;
vector<pii> adj[LIM];

int dfs(int nd,int ct,int pr)
{
	/*if(visited[nd])
		return -1;*/
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	par.insert(mp(mp(nd,ct),pr));
	if(nd==0)
	{
		dp[nd][ct] = 0;
		return 0;
	}
	//visited[nd] = true;
	int dis = INT_MAX;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct+1,nd)+edge.S;
		if(curr<dis)
		{
			dis = curr;
		}
	}
	//visited[nd] = false;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	cost.clear();
	par.clear();
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		cost.insert(mp(mp(u,v),w));
		adj[v].pb(mp(u,w));
	}
	//REP(i,n) REP(j,n) print(cost[i][j]);
	//visited.clear();
	//REP(i,n) visited.pb(false);
	dfs(n-1,0,-1);

	REPD(i,n)
	{
		//print(dp[n-1][i]);
		if(dp[0][i]!=-1)
		{
			vi v;
			int nd,ct;
			nd = 0;
			ct = i;
			bool ex = true;
			int sum = 0;
			while(nd!=-1)
			{
				v.pb(nd+1);
				if(sum>T)
				{
					ex = false;
					//debug3(sum,nd,"HOLA:()");
					break;
				}
				int pp = par[mp(nd,ct--)];
				int cc = cost[mp(nd,pp)];
				sum+=cc;
				nd = pp;
			}
			if(ex)
			{
				//print(tt);
				print(v.size());
				for(int x : v)
					cout << x << " ";
				cout << "\n";
				return;
			}
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
int par[LIM][LIM];
vector<pii> adj[LIM];

int dfs(int nd,int ct)
{
	if(ct<0)
	{
		return INF;
	}
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	if(nd==0)
	{
		if(ct>0)
			return INF;
		dp[nd][ct] = 0;
		return 0;
	}
	int dis = INF;
	int nnn = -1;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct-1);
		if(curr==INF)
			continue;

		curr+=edge.S;
		if(curr<dis)
		{
			dis = curr;
			nnn = edge.F;
		}
	}
	//visited[nd] = false;
	par[nd][ct] = nnn;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	memset(par,-1,sizeof(int)*LIM*LIM);
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		adj[v].pb(mp(u,w));
	}
	REPD(i,n)
	{
		//print(dp[n-1][i]);
		int holy = dfs(n-1,i);
		//debug2(holy,i);
		if(holy<=T)
		{
			vi v;
			int nd,ct;
			nd = n-1,ct = i;
			while(nd!=0)
			{
				v.pb(nd+1);
				nd = par[nd][ct--];
			}
			v.pb(1);
			reverse(all(v));
			print(v.size());
			for(int x : v)
				cout << x << " ";
			cout << "\n";
			return;
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
map<pii,int> par;
map<pii,int> cost;
vector<bool> visited;
vector<pii> adj[LIM];

int dfs(int nd,int ct,int pr)
{
	if(visited[nd])
		return -1;
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	par.insert(mp(mp(nd,ct),pr));
	if(nd==0)
	{
		dp[nd][ct] = 0;
		return 0;
	}
	visited[nd] = true;
	int dis = INT_MAX;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct+1,nd)+edge.S;
		if(curr<dis)
		{
			dis = curr;
		}
	}
	visited[nd] = false;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	cost.clear();
	par.clear();
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		cost.insert(mp(mp(u,v),w));
		adj[v].pb(mp(u,w));
	}
	//REP(i,n) REP(j,n) print(cost[i][j]);
	visited.clear();
	REP(i,n) visited.pb(false);
	dfs(n-1,0,-1);

	/*
	//Iterative DFS
	struct node{int nd;int ct;int pr;};
	stack<node> stck;
	stck.push({n-1,0,-1});
	while(!stck.empty())
	{
		node x = stck.top();
		if(dp[x.nd][x.ct]!=-1)
		{
			//debug("Happy New Year");
			stck.pop();
			continue;
		}
		//par[x.nd][x.ct] = x.pr;
		par.insert(mp(mp(x.nd,x.ct),x.pr));
		if(x.nd==0)
		{
			dp[x.nd][x.ct] = 0;
			stck.pop();
			continue;
		}
		visited[x.nd] = true;
		int dis = INT_MAX;
		bool ok = true;
		if(x.nd==n-1)
		{
			int xx = 0;
		}
		for(pii edge : adj[x.nd])
		{
			if(visited[edge.F])
				continue;
			if(dp[edge.F][x.ct+1]==-1)
			{
				ok = false;
				stck.push({edge.F,x.ct+1,x.nd});
				break;
			}
			int curr = dp[edge.F][x.ct+1]+edge.S;
			if(curr<dis)
			{
				dis = curr;
			}
		}
		if(!ok) continue;
		visited[x.nd] = false;
		dp[x.nd][x.ct] = dis;
		stck.pop();
	}
	//End of Iterative DFS
	*/

	REPD(i,n)
	{
		//print(dp[n-1][i]);
		if(dp[0][i]!=-1)
		{
			vi v;
			int nd,ct;
			nd = 0;
			ct = i;
			bool ex = true;
			int sum = 0;
			while(nd!=-1)
			{
				v.pb(nd+1);
				if(sum>T)
				{
					ex = false;
					//debug3(sum,nd,"HOLA:()");
					break;
				}
				int pp = par[mp(nd,ct--)];
				int cc = cost[mp(nd,pp)];
				if(pp>INF)
				{
					throw invalid_argument("CHOUD");
				}
				sum+=cc;
				nd = pp;
			}
			if(ex)
			{
				//print(tt);
				print(v.size());
				for(int x : v)
					cout << x << " ";
				cout << "\n";
				return;
			}
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
map<pii,int> par;
vector<pii> adj[LIM];

int dfs(int nd,int ct)
{
	if(ct<0)
	{
		return INT_MAX;
	}
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	if(nd==0)
	{
		if(ct>0)
			return INT_MAX;
		dp[nd][ct] = 0;
		return 0;
	}
	int dis = INT_MAX;
	int nnn = -1;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct-1);
		if(curr==INT_MAX)
			continue;

		curr+=edge.S;
		if(curr<dis)
		{
			dis = curr;
			nnn = edge.F;
		}
	}
	//visited[nd] = false;
	par.insert(mp(mp(nd,ct),nnn));
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	par.clear();
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		adj[v].pb(mp(u,w));
	}
	REPD(i,n)
	{
		//print(dp[n-1][i]);
		int holy = dfs(n-1,i);
		//debug2(holy,i);
		if(holy<=T)
		{
			vi v;
			int nd,ct;
			nd = n-1,ct = i;
			while(nd!=0)
			{
				v.pb(nd+1);
				nd = par[mp(nd,ct--)];
			}
			v.pb(1);
			reverse(all(v));
			print(v.size());
			for(int x : v)
				cout << x << " ";
			cout << "\n";
			return;
		}
		else
		{
			par.clear();
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define pb push_back
#define INF 1234567890
#define MOD 1000000007
#define PI atan(1)*4
#define mp make_pair
#define REP(i,n) for (int i = 0; i < n; i++)
#define FOR(i,a,b) for (int i = a; i <=b; i++)
#define REPD(i,n) for (int i = n-1; i >= 0; i--)
#define all(v) v.begin(),v.end()
#define pii pair<int,int>
#define F first
#define S second
#define mii map<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define itr :: iterator it
#define WL(t) while(t --)
#define gcd(a,b) __gcd((a),(b))
#define lcm(a,b) ((a)*(b))/gcd((a),(b))
#define print(x) cout << x << "\n";
#define debug(x) cout << x << "\n";
#define debug2(x,y) cout << x << " " << y << "\n";
#define debug3(x,y,z) cout << x << " " << y << " " << z << "\n";
#define debug4(x,y,z,zz) cout << x << " " << y << " " << z <<" "<<zz << "\n";
#define debug5(x,y,z,zz,yy) cout << x << " " << y << " " << z <<" "<<zz << " "<< yy << "\n";
const int LIM = 5000+5;

/* AUTHOR : Jagreet 'v01d' Das Gupta */

using namespace std;

void solve();
signed main()
{
	#ifndef ONLINE_JUDGE
	freopen("../input.txt","r",stdin);
	freopen("../output.txt","w",stdout);
	#else
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	#endif
	int t = 1;
	//cin >> t;
	WL(t) solve();
}

int n,m,T;
int dp[LIM][LIM];
map<pii,int> par;
vector<pii> adj[LIM];

int dfs(int nd,int ct)
{
	if(ct<0)
	{
		return INT_MAX;
	}
	if(dp[nd][ct]!=-1)
	{
		//debug("Happy New Year");
		return dp[nd][ct];
	}
	if(nd==0)
	{
		if(ct>0)
			return INT_MAX;
		dp[nd][ct] = 0;
		return 0;
	}
	int dis = INT_MAX;
	for(pii edge : adj[nd])
	{
		int curr = dfs(edge.F,ct-1);
		if(curr==INT_MAX)
			continue;
		curr+=edge.S;
		if(curr<dis)
		{
			dis = curr;
			par.insert(mp(mp(nd,ct),edge.F));
		}
	}
	//visited[nd] = false;
	dp[nd][ct] = dis;
	return dis;
}

void solve()
{
	cin >> n >> m >> T;
	memset(dp,-1,sizeof(int)*LIM*LIM);
	par.clear();
	REP(i,n) adj[i] = vector<pii>();
	REP(i,m)
	{
		int u,v,w;
		cin >> u >> v >> w;
		u--;v--;
		adj[v].pb(mp(u,w));
	}
	REPD(i,n)
	{
		//print(dp[n-1][i]);
		int holy = dfs(n-1,i);
		//debug2(holy,i);
		if(holy<=T)
		{
			vi v;
			int nd,ct;
			nd = n-1,ct = i;
			while(nd!=0)
			{
				v.pb(nd+1);
				nd = par[mp(nd,ct--)];
			}
			v.pb(1);
			reverse(all(v));
			print(v.size());
			for(int x : v)
				cout << x << " ";
			cout << "\n";
			return;
		}
		else
		{
			memset(dp,-1,sizeof(int)*LIM*LIM);
			par.clear();
		}
	}
	throw invalid_argument("HOLY MOLLY");
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class C2 {
    static class FastWriter {
        private final BufferedWriter bw;

        public FastWriter() {
            this.bw = new BufferedWriter(new OutputStreamWriter(System.out));
        }

        public void print(Object object) throws IOException {
            bw.append("" + object);
        }

        public void println(Object object) throws IOException {
            print(object);
            bw.append("\n");
        }

        public void close() throws IOException {
            bw.close();
        }
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        BigInteger nextBigInteger() {
            try {
                return new BigInteger(nextLine());
            } catch (NumberFormatException e) {
                throw new InputMismatchException();
            }
        }
    }

    static class pair implements Comparable<pair> {
        int a;
        int b;
        int c;
        int id;

        pair(int a, int b, int c, int id) {
            this.a = a;
            this.b = b;
            this.c = c;
            this.id = id;
        }

        @Override
        public int compareTo(pair o) {
            if (o.a == this.a && o.b == this.b) return this.c - o.c;
            if (o.a == this.a) return this.b - o.b;
            return this.a - o.a;
        }
    }

    public static void main(String[] args) throws IOException {
        FastReader fr = new FastReader();
        FastWriter fw = new FastWriter();
        int n = fr.nextInt();
        ArrayList<pair> list = new ArrayList<>();
        for (int i = 0; i < n; i++) list.add(new pair(fr.nextInt(), fr.nextInt(), fr.nextInt(), i + 1));
        list.sort(null);
        boolean visited[] = new boolean[list.size()];
        for (int i = 0; i < list.size() - 1; i++) {
            if (visited[i]) continue;
            pair x = list.get(i);
            pair y = list.get(i + 1);
            if ((x.a == y.a && x.b == y.b) || (x.a == y.a && x.c == y.c) || (x.c == y.c && x.b == y.b)) {
                fw.println(x.id + " " + y.id);
                visited[i] = visited[i + 1] = true;
            }
        }
        ArrayList<pair> rem = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            if (!visited[i]) rem.add(list.get(i));
        }
        visited = new boolean[rem.size()];
        for (int i = 0; i < rem.size() - 1; i++) {
            if (visited[i]) continue;
            pair x = rem.get(i);
            pair y = rem.get(i + 1);
            if (x.a == y.a || x.b == y.b || x.c == y.c) {
                fw.println(x.id + " " + y.id);
                visited[i] = visited[i + 1] = true;
            }
        }

        ArrayList<pair> rem2 = new ArrayList<>();
        for (int i = 0; i < rem.size(); i++) {
            if (!visited[i]) rem2.add(rem.get(i));
        }

        for (int i = 0; i < rem2.size(); i += 2) {
            fw.println(rem2.get(i).id + " " + rem2.get(i + 1).id);
        }
        fw.close();

    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
import java.util.InputMismatchException;
import java.util.StringTokenizer;

public class C2 {
    static class FastWriter {
        private final BufferedWriter bw;

        public FastWriter() {
            this.bw = new BufferedWriter(new OutputStreamWriter(System.out));
        }

        public void print(Object object) throws IOException {
            bw.append("" + object);
        }

        public void println(Object object) throws IOException {
            print(object);
            bw.append("\n");
        }

        public void close() throws IOException {
            bw.close();
        }
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        BigInteger nextBigInteger() {
            try {
                return new BigInteger(nextLine());
            } catch (NumberFormatException e) {
                throw new InputMismatchException();
            }
        }
    }

    static class pair implements Comparable<pair> {
        int a;
        int b;
        int c;
        int id;

        pair(int a, int b, int c, int id) {
            this.a = a;
            this.b = b;
            this.c = c;
            this.id = id;
        }

        @Override
        public int compareTo(pair o) {
            if (o.a == this.a && o.b == this.b) return this.c - o.c;
            if (o.a == this.a) return this.b - o.b;
            return this.a - o.a;
        }
    }

    public static void main(String[] args) throws IOException {
        FastReader fr = new FastReader();
        FastWriter fw = new FastWriter();
        int n = fr.nextInt();
        pair[] arr = new pair[n];
        for (int i = 0; i < n; i++) arr[i] = new pair(fr.nextInt(), fr.nextInt(), fr.nextInt(),i + 1);
        Arrays.sort(arr);
        boolean[] snap = new boolean[n];
        int l = 0;
        int r = 1;
        while (r < n) {
            while (l < n && snap[l]) l++;
            while (r < n && snap[r]) r++;
            if (l == r) r++;
            while (r < n && snap[r]) r++;
            if(r >= n || l >= n)break;
            pair lp = arr[l];
            pair rp = arr[r];
            if ((lp.a == rp.a && lp.b == rp.b) || (lp.b == rp.b && lp.c == rp.c) || ((lp.a == rp.a && lp.c == rp.c))) {
                fw.println(arr[l].id + " " + arr[r].id);
                snap[l] = snap[r] = true;
            }
            r++;
            l++;
        }
        l = 0;
        r = 1;
        while (r < n) {
            while (l < n && snap[l]) l++;
            while (r < n && snap[r]) r++;
            if (l == r) r++;
            while (r < n && snap[r]) r++;
            if(r >= n || l >= n)break;
            pair lp = arr[l];
            pair rp = arr[r];
            if (lp.a == rp.a || lp.b == rp.b || lp.c == rp.c) {
                fw.println(arr[l].id + " " + arr[r].id);
                snap[l] = snap[r] = true;
            }
            r++;
            l++;
        }
        l = 0;
        r = 1;
        while (r < n) {
            while (l < n && snap[l]) l++;
            while (r < n && snap[r]) r++;
            if (l == r) r++;
            while (r < n && snap[r]) r++;
            if(r >= n || l >= n)break;
            fw.println(arr[l].id + " " + arr[r].id);
            snap[l] = snap[r] = true;
            r++;
            l++;
        }
        fw.close();
    }
}


import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;

public class Solution implements Runnable {

	private PrintStream out;
	private BufferedReader in;
	private StringTokenizer st;

	public void solve() throws IOException {
		long time0 = System.currentTimeMillis();

		int n = nextInt();
		int[] x = new int[n];
		int[] y = new int[n];
		int[] z = new int[n];
		for (int i = 0; i < n; i++) {
			x[i] = nextInt();
			y[i] = nextInt();
			z[i] = nextInt();
		}
		int[][] answer = solve(n, x, y, z);
		for (int i = 0; i < answer.length; i++) {
			int a = answer[i][0] + 1;
			int b = answer[i][1] + 1;
			out.println(a + " " + b);
		}

		System.err.println("time: " + (System.currentTimeMillis() - time0));
	}

	private int[][] solve(int n, int[] x, int[] y, int[] z) {
		List<int[]> answer = new ArrayList<>();
		Point[] p = new Point[n];
		for (int i = 0; i < n; i++) {
			p[i] = new Point(x[i], y[i], z[i], i);
		}
		Point rem = solve(0, p, answer);
		if (rem != null) {
			throw new RuntimeException("Botva!");
		}
		return answer.toArray(new int[n / 2][]);
	}

	private Point solve(int axis, Point[] p, List<int[]> answer) {
		if (p.length == 0) {
			return null;
		}
		if (p.length == 1) {
			return p[0];
		}
		if (p.length == 2) {
			answer.add(new int[] {p[0].id, p[1].id});
			return null;
		}
		int minc = p[0].c[axis];
		int maxc = p[0].c[axis];
		for (int i = 1; i < p.length; i++) {
			minc = Math.min(minc, p[i].c[axis]);
			maxc = Math.max(maxc, p[i].c[axis]);
		}
		double midc = (minc + maxc) / 2.0;
		List<Point> p0 = new ArrayList<>();
		List<Point> p1 = new ArrayList<>();
		for (int i = 0; i < p.length; i++) {
			if (p[i].c[axis] < midc) {
				p0.add(p[i]);
			} else {
				p1.add(p[i]);
			}
		}
		Point p0rem = solve((axis + 1) % 3, p0.toArray(new Point[p0.size()]), answer);
		Point p1rem = solve((axis + 1) % 3, p1.toArray(new Point[p1.size()]), answer);
		if (p0rem == null) {
			if (p1rem == null) {
				return null;
			} else {
				return p1rem;
			}
		} else {
			if (p1rem == null) {
				return p0rem;
			} else {
				answer.add(new int[] {p0rem.id, p1rem.id});
				return null;
			}
		}
	}

	private static final class Point {
		private int[] c;
		private int id;
		private Point(int x, int y, int z, int id) {
			this.c = new int[] {x, y, z};
			this.id = id;
		}
		public String toString() {
			return "{" + c[0] + ", " + c[1] + ", " + c[2] + ", id=" + id + "}";
		}
	}

	public double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	public long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	public int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	public String next() throws IOException {
		while (!st.hasMoreTokens()) {
			String line = in.readLine();
			if (line == null) {
				return null;
			}
			st = new StringTokenizer(line);
		}
		return st.nextToken();
	}

	@Override
	public void run() {
		try {
			solve();
			out.close();
		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
	}

	public Solution(String name) throws IOException {
		Locale.setDefault(Locale.US);
		if (name == null) {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintStream(new BufferedOutputStream(System.out));
		} else {
			in = new BufferedReader(new InputStreamReader(new FileInputStream(name + ".in")));
			out = new PrintStream(new BufferedOutputStream(new FileOutputStream(name + ".out")));
		}
		st = new StringTokenizer("");
	}

	public static void main(String[] args) throws IOException {
		new Thread(new Solution(null)).start();
	}
}


import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;

public class Solution implements Runnable {

	public static final int INF = 100000001;

	private PrintStream out;
	private BufferedReader in;
	private StringTokenizer st;

	public void solve() throws IOException {
		long time0 = System.currentTimeMillis();

		int n = nextInt();
		int[] x = new int[n];
		int[] y = new int[n];
		int[] z = new int[n];
		for (int i = 0; i < n; i++) {
			x[i] = nextInt();
			y[i] = nextInt();
			z[i] = nextInt();
		}
		int[][] answer = solve(n, x, y, z);
		for (int i = 0; i < answer.length; i++) {
			int a = answer[i][0] + 1;
			int b = answer[i][1] + 1;
			out.println(a + " " + b);
		}

		System.err.println("time: " + (System.currentTimeMillis() - time0));
	}

	private int[][] solve(int n, int[] x, int[] y, int[] z) {
		List<int[]> answer = new ArrayList<>();
		int[][] p = new int[n][4];
		for (int i = 0; i < n; i++) {
			p[i][0] = x[i];
			p[i][1] = y[i];
			p[i][2] = z[i];
			p[i][3] = i;
		}
		solve(0, new int[][] {{-INF, -INF, -INF}, {INF, INF, INF}}, p, answer);
		return answer.toArray(new int[n / 2][]);
	}

	private void solve(int axis, int[][] box, int[][] p, List<int[]> answer) {
		if (p.length == 0) {
			return;
		}
		int[][][] newboxes = split_box(axis, box);
		int[][][] newpoints = split_points(newboxes, p);
		solve((axis + 1) % 3, newboxes[0], newpoints[0], answer);
		solve((axis + 1) % 3, newboxes[1], newpoints[1], answer);
		if (newpoints[2].length > 0) {
			answer.add(new int[] {newpoints[2][0][3], newpoints[2][1][3]});
		}
	}

	private int[][][] split_points(int[][][] boxes, int[][] p) {
		int cnt0 = 0;
		int cnt1 = 0;
		for (int i = 0; i < p.length; i++) {
			if (inside_box(p[i], boxes[0])) {
				cnt0++;
			} else {
				cnt1++;
			}
		}
		int[][][] result = new int[3][][];
		result[0] = new int[cnt0 - (cnt0 % 2)][];
		result[1] = new int[cnt1 - (cnt1 % 2)][];
		result[2] = new int[(cnt0 % 2) + (cnt1 % 2)][];
		cnt0 = 0;
		cnt1 = 0;
		int cnt2 = 0;
		for (int i = 0; i < p.length; i++) {
			if (inside_box(p[i], boxes[0])) {
				if (cnt0 < result[0].length) {
					result[0][cnt0++] = p[i];
				} else {
					result[2][cnt2++] = p[i];
				}
			} else {
				if (cnt1 < result[1].length) {
					result[1][cnt1++] = p[i];
				} else {
					result[2][cnt2++] = p[i];
				}
			}
		}
		return result;
	}

	private boolean inside_box(int[] p, int[][] box) {
		for (int i = 0; i < 3; i++) {
			if (p[i] < box[0][i] || p[i] >= box[1][i]) {
				return false;
			}
		}
		return true;
	}

	private int[][][] split_box(int axis, int[][] box) {
		int[] cmin = box[0];
		int[] cmax = box[1];
		int[][][] result = new int[2][2][3];
		int cmid = (cmin[axis] + cmax[axis]) / 2;
		result[0][0] = cmin.clone();
		result[0][1] = cmax.clone();
		result[0][1][axis] = cmid;
		result[1][0] = cmin.clone();
		result[1][1] = cmax.clone();
		result[1][0][axis] = cmid;
		return result;
	}

	public double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	public long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	public int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	public String next() throws IOException {
		while (!st.hasMoreTokens()) {
			String line = in.readLine();
			if (line == null) {
				return null;
			}
			st = new StringTokenizer(line);
		}
		return st.nextToken();
	}

	@Override
	public void run() {
		try {
			solve();
			out.close();
		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
	}

	public Solution(String name) throws IOException {
		Locale.setDefault(Locale.US);
		if (name == null) {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintStream(new BufferedOutputStream(System.out));
		} else {
			in = new BufferedReader(new InputStreamReader(new FileInputStream(name + ".in")));
			out = new PrintStream(new BufferedOutputStream(new FileOutputStream(name + ".out")));
		}
		st = new StringTokenizer("");
	}

	public static void main(String[] args) throws IOException {
		new Thread(new Solution(null)).start();
	}
}


import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale;
import java.util.StringTokenizer;

public class Solution implements Runnable {

	private PrintStream out;
	private BufferedReader in;
	private StringTokenizer st;

	public void solve() throws IOException {
		long time0 = System.currentTimeMillis();

		int n = nextInt();
		int[] x = new int[n];
		int[] y = new int[n];
		int[] z = new int[n];
		for (int i = 0; i < n; i++) {
			x[i] = nextInt();
			y[i] = nextInt();
			z[i] = nextInt();
		}
		int[][] answer = solve(n, x, y, z);
		for (int i = 0; i < answer.length; i++) {
			int a = answer[i][0] + 1;
			int b = answer[i][1] + 1;
			out.println(a + " " + b);
		}

		System.err.println("time: " + (System.currentTimeMillis() - time0));
	}

	private int[][] solve(int n, int[] x, int[] y, int[] z) {
		Integer[] id = new Integer[n];
		for (int i = 0; i < n; i++) {
			id[i] = i;
		}
		Arrays.sort(id, new Comparator<Integer>() {
			@Override
			public int compare(Integer i0, Integer i1) {
				if (x[i0] < x[i1]) {
					return -1;
				}
				if (x[i0] > x[i1]) {
					return 1;
				}
				if (y[i0] < y[i1]) {
					return -1;
				}
				if (y[i0] > y[i1]) {
					return 1;
				}
				if (z[i0] < z[i1]) {
					return -1;
				}
				if (z[i0] > z[i1]) {
					return 1;
				}
				return 0;
			}
		});
		int[][] answer = new int[n / 2][2];
		for (int i = 0; i < n; i++) {
			answer[i / 2][i % 2] = id[i];
		}
		return answer;
	}

	public double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	public long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	public int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	public String next() throws IOException {
		while (!st.hasMoreTokens()) {
			String line = in.readLine();
			if (line == null) {
				return null;
			}
			st = new StringTokenizer(line);
		}
		return st.nextToken();
	}

	@Override
	public void run() {
		try {
			solve();
			out.close();
		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
	}

	public Solution(String name) throws IOException {
		Locale.setDefault(Locale.US);
		if (name == null) {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintStream(new BufferedOutputStream(System.out));
		} else {
			in = new BufferedReader(new InputStreamReader(new FileInputStream(name + ".in")));
			out = new PrintStream(new BufferedOutputStream(new FileOutputStream(name + ".out")));
		}
		st = new StringTokenizer("");
	}

	public static void main(String[] args) throws IOException {
		new Thread(new Solution(null)).start();
	}
}


// package com.company;
import java.util.*;
import java.lang.*;
import java.io.*;
//****Use Integer Wrapper Class for Arrays.sort()****
public class AP3 {
    public static void main(String[] Args) {
        FastReader scan = new FastReader();
        int n = scan.nextInt();
        P[] ps=new P[n];
        Map<Long,ArrayList<P>> zm=new HashMap<>();
        for(int i=0;i<n;i++){
            long x=scan.nextLong();
            long y=scan.nextLong();
            long z=scan.nextLong();
            ps[i]=new P(i+1,x,y,z);
            zm.putIfAbsent(z,new ArrayList<>());
            zm.get(z).add(ps[i]);
        }
        StringBuilder ans=new StringBuilder();
        ArrayList<P> ztra=new ArrayList<>();
        for(Long z:zm.keySet()){
            ArrayList<P> cur=zm.get(z);
            Map<Long,ArrayList<P>> xm=new HashMap<>();
            for(P p:cur){
                xm.putIfAbsent(p.x,new ArrayList<>());
                xm.get(p.x).add(p);
            }
            ArrayList<P> xtra=new ArrayList<>();
            for(Long x:xm.keySet()){
                ArrayList<P> cy=xm.get(x);
                Collections.sort(cy,new yc());
                if(cy.size()%2!=0){
                    xtra.add(cy.remove(cy.size()-1));
                }
                for(int i=0;i<cy.size()-1;i+=2){
                    ans.append(cy.get(i).id+" "+cy.get(i+1).id+"\n");
                }
            }
            Collections.sort(xtra,new xc());
            if(xtra.size()%2!=0){
                ztra.add(xtra.remove(xtra.size()-1));
            }
            for(int i=0;i<xtra.size()-1;i+=2){
                ans.append(xtra.get(i).id+" "+xtra.get(i+1).id+"\n");
            }
        }
        Collections.sort(ztra,new zc());
        for(int i=0;i<ztra.size()-1;i+=2){
            ans.append(ztra.get(i).id+" "+ztra.get(i+1).id+"\n");
        }
        System.out.println(ans);
    }
    static class zc implements Comparator<P>{
        @Override
        public int compare(P o1, P o2) {
            if(o1.z>o2.z){
                return 1;
            }
            else{
                if(o1.z==o2.z){
                    return 0;
                }
                return-1;
            }
        }
    }
    static class yc implements Comparator<P>{
        @Override
        public int compare(P o1, P o2) {
            if(o1.y>o2.y){
                return 1;
            }
            else{
                if(o1.y==o2.y){
                    return 0;
                }
                return-1;
            }
        }
    }
    static class xc implements Comparator<P>{
        @Override
        public int compare(P o1, P o2) {
            if(o1.x>o2.x){
                return 1;
            }
            else{
                if(o1.x==o2.x){
                    return 0;
                }
                return-1;
            }
        }
    }
    static class P{
        int id;
        long x;
        long y;
        long z;
        P(int id,long x,long y,long z){
            this.id=id;
            this.x=x;
            this.y=y;
            this.z=z;
        }
    }
    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new
                    InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

        double nextDouble()
        {
            return Double.parseDouble(next());
        }

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }

}


import java.io.*;
import java.util.*;

public class Main {

    static FastReader in;
    static PrintWriter out;

    static ArrayList<Pair> ans;

    static class Pair {
        int i, j;

        Pair(int i, int j) {
            this.i = i;
            this.j = j;
        }

//        @Override
//        public int hashCode() {
//            int h = 1;
//            h = h * 31 + i;
//            h = h * 31 + j;
//            return h;
//        }
//
//        @Override
//        public boolean equals(Object o) {
//            if (this == o) return true;
//            if (!(o instanceof Pair)) return false;
//            Pair p = (Pair) o;
//            return i == p.i && j == p.j;
//        }
    }

    static class Trio {
        int i;
        long a, b;

        Trio(int i, long a, long b) {
            this.i = i;
            this.a = a;
            this.b = b;
        }

        @Override
        public int hashCode() {
            int h = 1;
            h = h * 31 + i;
            h = h * 31 + (int) a;
            h = h * 31 + (int) b;
            return h;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof Pair)) return false;
            Trio t = (Trio) o;
            return i == t.i && a == t.a && b == t.b;
        }
    }

    static void solve() {
        int n = in.nextInt();

        long[][] a = new long[n][3];
        for (int i = 0; i < n; i++) {
            a[i][0] = in.nextLong();
            a[i][1] = in.nextLong();
            a[i][2] = in.nextLong();
        }

        Arrays.sort(a, new Comparator<long[]>() {
            @Override
            public int compare(long[] o1, long[] o2) {
                if (o1[0] == o2[0]) {
                    if (o1[1] == o2[1]) {
                        return Long.compare(o1[2], o2[2]);
                    }
                    return Long.compare(o1[1], o2[1]);
                }
                return Long.compare(o1[0], o2[0]);
            }
        });

        boolean[] were = new boolean[n];

        ans = new ArrayList<>();
        ArrayList<Integer> l1 = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            int j = i;
            while (j < n && a[j][0] == a[i][0]) {
                j++;
            }
            if ((j - i) % 2 == 1) {
                l1.add(i);
                i++;
            }

            ArrayList<Integer> l2 = new ArrayList<>();
            for (int k = i; k < j; k++) {
                if (k + 1 < j && a[k][1] == a[k + 1][1]) {
                    ans.add(new Pair(k, k + 1));
                    k++;
                } else {
                    l2.add(k);
                }
            }

            for (int l = 0; l < l2.size(); l += 2) {
                ans.add(new Pair(l2.get(l), l2.get(l + 1)));
            }

            i = j - 1;

        }
        for (int j = 0; j < l1.size(); j += 2) {
            ans.add(new Pair(l1.get(j), l1.get(j + 1)));
        }

        for (Pair p : ans) {
            out.println((p.i+1) + " " + (p.j+1));
        }
    }

    public static void main(String[] args) {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("input.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int q = 1;

        while (q-- > 0)
            solve();

        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }
}


import java.io.*;
import java.util.*;

public class Main {

    static FastReader in;
    static PrintWriter out;

    static class Pair {
        int i, j;

        Pair(int i, int j) {
            this.i = i;
            this.j = j;
        }
    }

    static class Point {
        int i, x, y, z;

        Point(int i, int x, int y, int z) {
            this.i = i;
            this.x = x;
            this.y = y;
            this.z = z;
        }

//        @Override
//        public int hashCode() {
//            int h = 1;
//            h = 37 * h + i;
//            h = 37 * h + x;
//            h = 37 * h + y;
//            h = 37 * h + z;
//            return h;
//        }
//
//        @Override
//        public boolean equals(Object o) {
//            if (this == o) return true;
//            if (!(o instanceof Point)) return false;
//            Point p = (Point) o;
//            return i == p.i && x == p.x && y == p.y && z == p.z;
//        }
    }

    static void solve() {
        int n = in.nextInt();

        ArrayList<Point> points = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            points.add(new Point(i, in.nextInt(), in.nextInt(), in.nextInt()));
        }

        points.sort(new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                if (o1.x == o2.x) {
                    if (o1.y == o2.y) {
                        return o1.z - o2.z;
                    }
                    return o1.y - o2.y;
                }
                return o1.x - o2.x;
            }
        });

        ArrayList<Pair> ans = new ArrayList<>();
        ArrayList<Integer> lx = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            int ind = i;
            while (ind < n && points.get(ind).x == points.get(i).x) ind++;

            if ((ind - i) % 2 == 1) {
                lx.add(points.get(i).i);
                i++;
            }

            ArrayList<Integer> ly = new ArrayList<>();
            for (int j = i; j < ind; j++) {
                if (points.get(j).y == points.get(j + 1).y) {
                    ans.add(new Pair(points.get(j).i, points.get(j + 1).i));
                    j++;
                } else {
                    ly.add(points.get(j).i);
                }
            }
            for (int j = 0; j < ly.size(); j += 2) {
                ans.add(new Pair(ly.get(j), ly.get(j + 1)));
            }

            i = ind - 1;
        }
        for (int i = 0; i < lx.size(); i += 2) {
            ans.add(new Pair(lx.get(i), lx.get(i + 1)));
        }

        for (Pair p : ans) {
            out.println((p.i + 1) + " " + (p.j + 1));
        }
    }

    public static void main(String[] args) {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("input.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int q = 1;

        while (q-- > 0)
            solve();

        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }
}


import java.io.*;
import java.util.*;

public class Main {

    static FastReader in;
    static PrintWriter out;

    static class Pair {
        int i, j;

        Pair(int i, int j) {
            this.i = i;
            this.j = j;
        }
    }

    static class Point {
        int i, x, y, z;

        Point(int i, int x, int y, int z) {
            this.i = i;
            this.x = x;
            this.y = y;
            this.z = z;
        }

//        @Override
//        public int hashCode() {
//            int h = 1;
//            h = 37 * h + i;
//            h = 37 * h + x;
//            h = 37 * h + y;
//            h = 37 * h + z;
//            return h;
//        }
//
//        @Override
//        public boolean equals(Object o) {
//            if (this == o) return true;
//            if (!(o instanceof Point)) return false;
//            Point p = (Point) o;
//            return i == p.i && x == p.x && y == p.y && z == p.z;
//        }
    }

    static void solve() {
        int n = in.nextInt();

        ArrayList<Point> points = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            points.add(new Point(i, in.nextInt(), in.nextInt(), in.nextInt()));
        }

        points.sort(new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                if (o1.x == o2.x) {
                    if (o1.y == o2.y) {
                        return o1.z - o2.z;
                    }
                    return o1.y - o2.y;
                }
                return o1.x - o2.x;
            }
        });

        ArrayList<Pair> ans = new ArrayList<>();
        ArrayList<Integer> lx = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            int ind = i;
            while (ind < n && points.get(ind).x == points.get(i).x) ind++;

            ArrayList<Integer> ly = new ArrayList<>();
            for (int j = i; j < ind; j++) {
                if (j + 1 < ind && points.get(j).y == points.get(j + 1).y) {
                    ans.add(new Pair(points.get(j).i, points.get(j + 1).i));
                    j++;
                } else {
                    ly.add(points.get(j).i);
                }
            }
            for (int j = 0; j < ly.size() - 1; j += 2) {
                ans.add(new Pair(ly.get(j), ly.get(j + 1)));
            }
            if ((ind - i) % 2 == 1) {
                lx.add(ly.get(ly.size() - 1));
            }

            i = ind - 1;
        }
        for (int i = 0; i < lx.size(); i += 2) {
            ans.add(new Pair(lx.get(i), lx.get(i + 1)));
        }

        for (Pair p : ans) {
            out.println((p.i + 1) + " " + (p.j + 1));
        }
    }

    public static void main(String[] args) {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("input.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int q = 1;

        while (q-- > 0)
            solve();

        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }
}


import java.io.*;
import java.util.*;

public class Main {

	static InputReader in = new InputReader(System.in);
	static PrintWriter out = new PrintWriter(System.out);

	static int oo = (int)1e9;
	static int mod = 1_000_000_007;

	static int[] di = {1, 0, 0, -1};
	static int[] dj = {0, -1, 1, 0};

	static int M = 200005;

	public static void main(String[] args) throws IOException {

		int n = in.nextInt();
		ArrayList<Loc> arr = new ArrayList<>();
		for(int i = 1; i <= n; ++i) {
			int x = in.nextInt();
			int y = in.nextInt();
			int z = in.nextInt();
			arr.add(new Loc(x, y, z, i));
		}
		Collections.sort(arr);
		ArrayList<Pair> remove = new ArrayList<>();
		boolean[] sel = new boolean[n+1];
		Loc p = null;
//		ArrayList<Loc> arr2 = new ArrayList<>();
		for(int i = 0; i < arr.size(); ++i) {
			if(p == null)
				p = arr.get(i);
			else {
				Loc q = arr.get(i);
				if(p.x == q.x && p.y == q.y) {
					remove.add(new Pair(p.idx, q.idx));
					sel[p.idx] = sel[q.idx] = true;
					p = null;
				}
				else {
					p = q;
				}
			}
		}
		p = null;
		for(int i = 0; i < arr.size(); ++i) {
			if(sel[arr.get(i).idx])
				continue;
			if(p == null)
				p = arr.get(i);
			else {
				Loc q = arr.get(i);
				if(p.x == q.x) {
					remove.add(new Pair(p.idx, q.idx));
					sel[p.idx] = sel[q.idx] = true;
					p = null;
				}
				else {
					p = q;
				}
			}
		}
		p = null;
		for(int i = 0; i < arr.size(); ++i) {
			if(sel[arr.get(i).idx])
				continue;
			if(p == null)
				p = arr.get(i);
			else {
				Loc q = arr.get(i);
				remove.add(new Pair(p.idx, q.idx));
				sel[p.idx] = sel[q.idx] = true;
				p = null;
			}
		}

		for(Pair pair : remove)
			System.out.println(pair.first + " " + pair.second);

		out.close();
	}

	static class Loc implements Comparable<Loc> {
		int x, y, z, idx;

		public Loc(int x, int y, int z, int idx) {
			super();
			this.x = x;
			this.y = y;
			this.z = z;
			this.idx = idx;
		}

		@Override
		public int compareTo(Loc o) {
			if(x != o.x)
				return x - o.x;
			if(y != o.y)
				return y - o.y;
			if(z != o.z)
				return z - o.z;
			return 0;
		}
	}

	static boolean inside(int i, int j, int n, int m) {
		return i >= 0 && i < n && j >= 0 && j < m;
	}

	static long pow(long a, long n, long mod) {
		if(n == 0)
			return 1;
		if(n % 2 == 1)
			return a * pow(a, n-1, mod) % mod;
		long x = pow(a, n / 2, mod);
		return x * x % mod;
	}

	static class SegmentTree {
		int n;
		char[] a;
		int[] seg;
		int DEFAULT_VALUE = 0;

		public SegmentTree(char[] a, int n) {
			super();
			this.a = a;
			this.n = n;
			seg = new int[n * 4 + 1];
			build(1, 0, n-1);
		}

		private int build(int node, int i, int j) {
			if(i == j) {
				int x = a[i] - 'a';
				return seg[node] = (1<<x);
			}
			int first = build(node * 2, i, (i+j) / 2);
			int second = build(node * 2 + 1, (i+j) / 2 + 1, j);
			return seg[node] = combine(first, second);
		}

		int update(int k, char value) {
			return update(1, 0, n-1, k, value);
		}

		private int update(int node, int i, int j, int k, char value) {
			if(k < i || k > j)
				return seg[node];
			if(i == j && j == k) {
				a[k] = value;
				int x = a[i] - 'a';
				return seg[node] = (1<<x);
			}
			int m = (i + j) / 2;
			int first = update(node * 2, i, m, k, value);
			int second = update(node * 2 + 1, m + 1, j, k, value);
			return seg[node] = combine(first, second);
		}

		int query(int l, int r) {
			return query(1, 0, n-1, l, r);
		}

		private int query(int node, int i, int j, int l, int r) {
			if(l <= i && j <= r)
				return seg[node];
			if(j < l || i > r)
				return DEFAULT_VALUE;
			int m = (i + j) / 2;
			int first = query(node * 2, i, m, l, r);
			int second = query(node * 2 + 1, m+1, j, l, r);
			return combine(first, second);
		}

		private int combine(int a, int b) {
			return a | b;
		}
	}

	static class DisjointSet {
		int n;
		int[] g;
		int[] h;
		public DisjointSet(int n) {
			super();
			this.n = n;
			g = new int[n];
			h = new int[n];
			for(int i = 0; i < n; ++i) {
				g[i] = i;
				h[i] = 1;
			}
		}
		int find(int x) {
			if(g[x] == x)
				return x;
			return g[x] = find(g[x]);
		}
		void union(int x, int y) {
			x = find(x); y = find(y);
			if(x == y)
				return;
			if(h[x] >= h[y]) {
				g[y] = x;
				if(h[x] == h[y])
					h[x]++;
			}
			else {
				g[x] = y;
			}
		}
	}

	static int[] getPi(char[] a) {
		int m = a.length;
		int j = 0;
		int[] pi = new int[m];
		for(int i = 1; i < m; ++i) {
			while(j > 0 && a[i] != a[j])
				j = pi[j-1];
			if(a[i] == a[j]) {
				pi[i] = j + 1;
				j++;
			}
		}
		return pi;
	}

	static long lcm(long a, long b) {
		return a * b / gcd(a, b);
	}

	static boolean nextPermutation(int[] a) {
		for(int i = a.length - 2; i >= 0; --i) {
			if(a[i] < a[i+1]) {
				for(int j = a.length - 1; ; --j) {
					if(a[i] < a[j]) {
						int t = a[i];
						a[i] = a[j];
						a[j] = t;
						for(i++, j = a.length - 1; i < j; ++i, --j) {
							t = a[i];
							a[i] = a[j];
							a[j] = t;
						}
						return true;
					}
				}
			}
		}
		return false;
	}

	static void shuffle(int[] a) {
		Random r = new Random();
		for(int i = a.length - 1; i > 0; --i) {
			int si = r.nextInt(i);
			int t = a[si];
			a[si] = a[i];
			a[i] = t;
		}
	}

	static void shuffle(long[] a) {
		Random r = new Random();
		for(int i = a.length - 1; i > 0; --i) {
			int si = r.nextInt(i);
			long t = a[si];
			a[si] = a[i];
			a[i] = t;
		}
	}

	static int lower_bound(int[] a, int n, int k) {
		int s = 0;
		int e = n;
		int m;
		while (e - s > 0) {
			m = (s + e) / 2;
			if (a[m] < k)
				s = m + 1;
			else
				e = m;
		}
		return e;
	}
	static int lower_bound(long[] a, int n, long k) {
		int s = 0;
		int e = n;
		int m;
		while (e - s > 0) {
			m = (s + e) / 2;
			if (a[m] < k)
				s = m + 1;
			else
				e = m;
		}
		return e;
	}

	static int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}
	static long gcd(long a, long b) {
		return b == 0 ? a : gcd(b, a % b);
	}

	static class Pair implements Comparable<Pair> {
		int first, second;

		public Pair(int first, int second) {
			super();
			this.first = first;
			this.second = second;
		}

		@Override
		public int compareTo(Pair o) {
			return this.first != o.first ? this.first - o.first : this.second - o.second;
		}

//		@Override
//		public int compareTo(Pair o) {
//			return this.first != o.first ? o.first - this.first : o.second - this.second;
//		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + first;
			result = prime * result + second;
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Pair other = (Pair) obj;
			if (first != other.first)
				return false;
			if (second != other.second)
				return false;
			return true;
		}
	}
}

class InputReader {

	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String readString() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isSpaceChar(c));
		return res.toString();
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}

}


import java.io.*;
import java.util.*;

public class Main {

	static InputReader in = new InputReader(System.in);
	static PrintWriter out = new PrintWriter(System.out);

	static int oo = (int)1e9;
	static int mod = 1_000_000_007;

	static int[] di = {1, 0, 0, -1};
	static int[] dj = {0, -1, 1, 0};

	static int M = 200005;

	public static void main(String[] args) throws IOException {

		int n = in.nextInt();
		ArrayList<Loc> arr = new ArrayList<>();
		for(int i = 1; i <= n; ++i) {
			int x = in.nextInt();
			int y = in.nextInt();
			int z = in.nextInt();
			arr.add(new Loc(x, y, z, i));
		}
		Collections.sort(arr);
		ArrayList<Pair> remove = new ArrayList<>();
		ArrayList<Loc> arr2 = new ArrayList<>();
		for(int i = 0; i < arr.size(); ++i) {
			Loc p = arr.get(i);
			if(i+1 < arr.size()) {
				Loc q = arr.get(i+1);
				if(p.x == q.x && p.y == q.y) {
					remove.add(new Pair(p.idx, q.idx));
					i++;
				}
				else {
					arr2.add(p);
				}
			}
			else {
				arr2.add(p);
			}
		}
		ArrayList<Loc> arr3 = new ArrayList<>();
		for(int i = 0; i < arr2.size(); ++i) {
			Loc p = arr2.get(i);
			if(i+1 < arr2.size()) {
				Loc q = arr2.get(i+1);
				if(p.x == q.x) {
					remove.add(new Pair(p.idx, q.idx));
					i++;
				}
				else {
					arr3.add(p);
				}
			}
			else {
				arr3.add(p);
			}
		}
		for(int i = 0; i < arr3.size() - 1; i += 2) {
			Loc p = arr3.get(i);
			Loc q = arr3.get(i+1);
			remove.add(new Pair(p.idx, q.idx));
		}
		for(Pair p : remove)
			System.out.println(p.first + " " + p.second);

		out.close();
	}

	static class Loc implements Comparable<Loc> {
		int x, y, z, idx;

		public Loc(int x, int y, int z, int idx) {
			super();
			this.x = x;
			this.y = y;
			this.z = z;
			this.idx = idx;
		}

		@Override
		public int compareTo(Loc o) {
			if(x != o.x)
				return x - o.x;
			if(y != o.y)
				return y - o.y;
			if(z != o.z)
				return z - o.z;
			return 0;
		}
	}

	static boolean inside(int i, int j, int n, int m) {
		return i >= 0 && i < n && j >= 0 && j < m;
	}

	static long pow(long a, long n, long mod) {
		if(n == 0)
			return 1;
		if(n % 2 == 1)
			return a * pow(a, n-1, mod) % mod;
		long x = pow(a, n / 2, mod);
		return x * x % mod;
	}

	static class SegmentTree {
		int n;
		char[] a;
		int[] seg;
		int DEFAULT_VALUE = 0;

		public SegmentTree(char[] a, int n) {
			super();
			this.a = a;
			this.n = n;
			seg = new int[n * 4 + 1];
			build(1, 0, n-1);
		}

		private int build(int node, int i, int j) {
			if(i == j) {
				int x = a[i] - 'a';
				return seg[node] = (1<<x);
			}
			int first = build(node * 2, i, (i+j) / 2);
			int second = build(node * 2 + 1, (i+j) / 2 + 1, j);
			return seg[node] = combine(first, second);
		}

		int update(int k, char value) {
			return update(1, 0, n-1, k, value);
		}

		private int update(int node, int i, int j, int k, char value) {
			if(k < i || k > j)
				return seg[node];
			if(i == j && j == k) {
				a[k] = value;
				int x = a[i] - 'a';
				return seg[node] = (1<<x);
			}
			int m = (i + j) / 2;
			int first = update(node * 2, i, m, k, value);
			int second = update(node * 2 + 1, m + 1, j, k, value);
			return seg[node] = combine(first, second);
		}

		int query(int l, int r) {
			return query(1, 0, n-1, l, r);
		}

		private int query(int node, int i, int j, int l, int r) {
			if(l <= i && j <= r)
				return seg[node];
			if(j < l || i > r)
				return DEFAULT_VALUE;
			int m = (i + j) / 2;
			int first = query(node * 2, i, m, l, r);
			int second = query(node * 2 + 1, m+1, j, l, r);
			return combine(first, second);
		}

		private int combine(int a, int b) {
			return a | b;
		}
	}

	static class DisjointSet {
		int n;
		int[] g;
		int[] h;
		public DisjointSet(int n) {
			super();
			this.n = n;
			g = new int[n];
			h = new int[n];
			for(int i = 0; i < n; ++i) {
				g[i] = i;
				h[i] = 1;
			}
		}
		int find(int x) {
			if(g[x] == x)
				return x;
			return g[x] = find(g[x]);
		}
		void union(int x, int y) {
			x = find(x); y = find(y);
			if(x == y)
				return;
			if(h[x] >= h[y]) {
				g[y] = x;
				if(h[x] == h[y])
					h[x]++;
			}
			else {
				g[x] = y;
			}
		}
	}

	static int[] getPi(char[] a) {
		int m = a.length;
		int j = 0;
		int[] pi = new int[m];
		for(int i = 1; i < m; ++i) {
			while(j > 0 && a[i] != a[j])
				j = pi[j-1];
			if(a[i] == a[j]) {
				pi[i] = j + 1;
				j++;
			}
		}
		return pi;
	}

	static long lcm(long a, long b) {
		return a * b / gcd(a, b);
	}

	static boolean nextPermutation(int[] a) {
		for(int i = a.length - 2; i >= 0; --i) {
			if(a[i] < a[i+1]) {
				for(int j = a.length - 1; ; --j) {
					if(a[i] < a[j]) {
						int t = a[i];
						a[i] = a[j];
						a[j] = t;
						for(i++, j = a.length - 1; i < j; ++i, --j) {
							t = a[i];
							a[i] = a[j];
							a[j] = t;
						}
						return true;
					}
				}
			}
		}
		return false;
	}

	static void shuffle(int[] a) {
		Random r = new Random();
		for(int i = a.length - 1; i > 0; --i) {
			int si = r.nextInt(i);
			int t = a[si];
			a[si] = a[i];
			a[i] = t;
		}
	}

	static void shuffle(long[] a) {
		Random r = new Random();
		for(int i = a.length - 1; i > 0; --i) {
			int si = r.nextInt(i);
			long t = a[si];
			a[si] = a[i];
			a[i] = t;
		}
	}

	static int lower_bound(int[] a, int n, int k) {
		int s = 0;
		int e = n;
		int m;
		while (e - s > 0) {
			m = (s + e) / 2;
			if (a[m] < k)
				s = m + 1;
			else
				e = m;
		}
		return e;
	}
	static int lower_bound(long[] a, int n, long k) {
		int s = 0;
		int e = n;
		int m;
		while (e - s > 0) {
			m = (s + e) / 2;
			if (a[m] < k)
				s = m + 1;
			else
				e = m;
		}
		return e;
	}

	static int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}
	static long gcd(long a, long b) {
		return b == 0 ? a : gcd(b, a % b);
	}

	static class Pair implements Comparable<Pair> {
		int first, second;

		public Pair(int first, int second) {
			super();
			this.first = first;
			this.second = second;
		}

		@Override
		public int compareTo(Pair o) {
			return this.first != o.first ? this.first - o.first : this.second - o.second;
		}

//		@Override
//		public int compareTo(Pair o) {
//			return this.first != o.first ? o.first - this.first : o.second - this.second;
//		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + first;
			result = prime * result + second;
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Pair other = (Pair) obj;
			if (first != other.first)
				return false;
			if (second != other.second)
				return false;
			return true;
		}
	}
}

class InputReader {

	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String readString() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isSpaceChar(c));
		return res.toString();
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}

}