// .... .... .....!
// ...... ......!
// .... ....... ..... ..!
// ...... ... ... .... ... .... .....!
// ... .. ... .... ...?
// ....... .. .... .. ...., ....... ..!

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

#define rep(i, n) for (int i = 0, i##__n = (int)(n); i < i##__n; ++i)
#define fer(i, a, b) for (int i = (int)(a), i##__b = (int)(b); i < i##__b; ++i)
#define rof(i, b, a) for (int i = (int)(b), i##__a = (int)(a); i-- > i##__a; )
#define sz(x) (int((x).size()))
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define X first
#define Y second
//#define endl '\n'

template<class P, class Q> inline void smin(P &a, Q b) { if (b < a) a = b; }
template<class P, class Q> inline void smax(P &a, Q b) { if (a < b) a = b; }

typedef long long ll;
typedef pair<int, int> pii;

////////////////////////////////////////////////////////////////////////////////

const int maxn = 200000 + 100;

int n;
vector<int> adj[maxn];
int sub_size[maxn];
bool is_centroid[maxn];
vector<int> vx, vy, vz;

void find_centroid(int u, int par = -1) {
	int max_sub = 0;
	sub_size[u] = 1;
	for(int v: adj[u]) if(v != par) {
		find_centroid(v, u);
		sub_size[u] += sub_size[v];
		smax(max_sub, sub_size[v]);
	}
	smax(max_sub, n - sub_size[u]);
	if(max_sub <= n / 2) is_centroid[u] = true;
}

int parent[maxn];
vector<int> stash;
void dfs(int u, int par, int depth = 0) {
	if(depth > 1) stash.pb(u);
	parent[u] = par;
	for(int v: adj[u]) if(v != par) dfs(v, u, depth + 1);
}

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

	cin >> n;
	rep(i, n-1) {
		int u, v; cin >> u >> v; u--, v--;
		adj[u].pb(v), adj[v].pb(u);
	}

	find_centroid(0);

	rep(c, n) if(is_centroid[c])
		for(int x: adj[c]) if(!is_centroid[x]) {
			stash.clear();
			dfs(x, c);
			int cur = x;
			for(int v: stash) {
				vx.pb(c), vy.pb(cur), vz.pb(v);
				cur = v;
				vx.pb(v), vy.pb(parent[v]), vz.pb(x);
			}
			if(cur != x) vx.pb(c), vy.pb(cur), vz.pb(x);
		}

	cout << sz(vx) << endl;
	rep(i, sz(vx)) cout << vx[i] + 1 << ' ' << vy[i] + 1 << ' ' << vz[i] + 1 << endl;

	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mt make_tuple
const int N=200050;
vector<int> E[N];
vector<tuple<int,int,int> > ans;
bool ctr[N];
int last,sz[N],n;
void DFSSZ(int u, int p)
{
	sz[u]=1;ctr[u]=1;
	for(int v:E[u]) if(v!=p)
	{
		DFSSZ(v,u);
		sz[u]+=sz[v];
		if(sz[v]>n/2) ctr[u]=0;
	}
	if(n-sz[u]>n/2) ctr[u]=0;
}
void DFS(int u, int p, int cen, int sku)
{
	for(int v:E[u]) if(v!=p && !ctr[v])
	{
		DFS(v,u,cen,sku);
		ans.pb(mt(cen,last,v));
		ans.pb(mt(v,u,sku));
		last=v;
	}
}
int main()
{
	int i,j,u,v;
	scanf("%i",&n);
	for(i=1;i<n;i++) scanf("%i %i",&u,&v),E[u].pb(v),E[v].pb(u);
	DFSSZ(1,0);
	vector<int> cns;
	for(i=1;i<=n;i++) if(ctr[i]) cns.pb(i);
	for(i:cns)
	{
		for(j:E[i]) if(!ctr[j])
		{
			last=j;
			DFS(j,i,i,j);
			ans.pb(mt(i,last,j));
		}
	}
	vector<tuple<int,int,int> > sol;
	for(i=0;i<ans.size();i++) if(get<1>(ans[i])!=get<2>(ans[i])) sol.pb(ans[i]);
	printf("%i\n",sol.size());
	for(auto p:sol) printf("%i %i %i\n",get<0>(p),get<1>(p),get<2>(p));
	return 0;
}//hello

#include <cstdlib>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <deque>
#include <iomanip>
#include <iostream>
#include <list>
#include <numeric>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <stack>

using namespace std;

#define sz(X) ((int)(X).size())
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define all(X) (X).begin(),(X).end()
#define FOR(i, a, n) for(int i=(a), __ ## i=(n); i<__ ## i; i++)
#define REP(I,N) FOR(I,0,N)
#define PR(X) cout<<#X<<" = "<<(X)<<" "
#define PRL cout<<endl
#define PRV(X) {cout<<#X<<" = {";REP(__prv,sz(X)-1)cout<<(X)[__prv]<<",";if(sz(X))cout<<*(X).end();cout<<"}"<<endl;}

template<class T> ostream &operator<<(ostream &os, const vector<T> &vec)
{
	os << '{';
	REP(i, sz(vec))
	{
		os << vec[i];
		if (i + 1 != sz(vec))
			os << ',';
	}
	os << '}';
	return os;
}

template<class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &par)
{
	os << '(' << par.X << ',' << par.Y << ')';
	return os;
}

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<bool> VB;
typedef vector<unsigned long long> VULL;
typedef vector<vector<int>> VVI;
typedef queue<int> QI;

int gcd(int x, int y)
{
	return y ? gcd(y, x % y) : abs(x);
}

template<class T> T sqr(T x)
{
	return x * x;
}

const LL MOD = 1e9 + 7;

//base ^ p
LL bin_pow(LL base, LL p) {
	if (p == 1)
		return base;

	if (p % 2 == 0) {
		LL t = bin_pow(base, p / 2);
		return t * t % MOD;
	}
	else
		return bin_pow(base, p - 1) * base % MOD;
}

LL inverse_element(LL x) {
	return bin_pow(x, MOD - 2);
}

//(a / b) mod m
LL divide(LL a, LL b) {
	return a * inverse_element(b) % MOD;
}

//(a * b) mod m
LL mult(LL a, LL b) {
	return (a * b) % MOD;
}

VI g[202020];
int c[202020];
int p[202020];
int ed[202020];
int d[202020];
bool used[202020];
int skip[202020];

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

	int n;
	cin >> n;

	REP(i, n - 1) {
		int a, b;
		cin >> a >> b;
		g[a - 1].pb(b - 1);
		g[b - 1].pb(a - 1);
	}

	if (n <= 3) {
		cout << 0;
		return 0;
	}

	VI ans;

	stack<int> st;
	st.push(0);
	p[0] = -1;
	while (!st.empty()) {
		int u = st.top();
		if (ed[u] == sz(g[u])) {
			c[u]++;
			if (p[u] != -1)
				c[p[u]] += c[u];
			st.pop();
			continue;
		}

		int v = g[u][ed[u]++];
		if (v != p[u]) {
			p[v] = u;
			st.push(v);
		}
	}

	VI centroids;

	int u = 0;
	while (true) {
		bool cent = (n - c[u] <= n / 2);
		int cur = u;
		REP(i, sz(g[u])) {
			int v = g[u][i];
			if (v == p[u])
				continue;
			if (c[v] > n / 2) {
				u = v;
				cent = false;
				break;
			}
			else if (c[v] == n / 2) {
				u = v;
				break;
			}
		}

		if (cent) {
			centroids.pb(cur);
			used[cur] = true;
		}
		if (cur == u)
			break;
	}

	REP(i, n)
		c[i] = ed[i] = 0;

	REP(j, sz(centroids)) {
		REP(i, sz(g[centroids[j]])){
			if (used[g[centroids[j]][i]])
				continue;

			vector<PII> leaves;

			st.push(g[centroids[j]][i]);
			skip[g[centroids[j]][i]] = p[g[centroids[j]][i]] = centroids[j];
			int deep = 0;
			while (!st.empty()) {
				int u = st.top();
				if (ed[u] == sz(g[u])) {
					if (c[u] == 0)
						leaves.pb({ deep, u });
					c[u]++;
					c[p[u]] += c[u];
					st.pop();
					deep--;
					continue;
				}

				int v = g[u][ed[u]++];
				if (!used[v] && v != p[u]) {
					skip[v] = p[v] = u;
					st.push(v);
					deep++;
				}
			}

			sort(all(leaves));
			REP(i, sz(leaves) - 1) {
				int u = leaves[i].second;
				while (ed[u] < 3) {
					d[p[u]] = u;
					u = p[u];
				}
				d[leaves[i].second] = p[u];

				ed[u]--;
				ans.pb(p[u]);
				ans.pb(u);
				ans.pb(leaves[i].second);

				while (u != d[leaves[i].second]) {
					p[u] = d[u];
					u = d[u];
				}
			}

			if (sz(leaves) > 0) {
				int leaf = leaves[sz(leaves) - 1].second;
				int u = p[leaf];
				while (!used[u]) {
					ans.pb(p[u]);
					ans.pb(u);
					ans.pb(leaf);
					u = p[u];
				}
			}
		}

	}

	cout << sz(ans) / 3;
	REP(i, sz(ans) / 3) {
		cout << endl << ans[i * 3] + 1 << ' ' << ans[i * 3 + 1] + 1 << ' ' << ans[i * 3 + 2] + 1 << ' ';
	}

	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mt make_tuple
const int N=200050;
vector<int> E[N];
vector<tuple<int,int,int> > ans;
bool ctr[N];
int last,sz[N],n;
void DFSSZ(int u, int p)
{
	sz[u]=1;ctr[u]=1;
	for(int v:E[u]) if(v!=p)
	{
		DFSSZ(v,u);
		sz[u]+=sz[v];
		if(sz[v]>n/2) ctr[u]=0;
	}
	if(n-sz[u]>n/2) ctr[u]=0;
}
void DFS(int u, int p, int cen, int sku)
{
	for(int v:E[u]) if(v!=p && !ctr[v])
	{
		DFS(v,u,cen,sku);
		ans.pb(mt(cen,last,v));
		ans.pb(mt(v,u,sku));
		last=v;
	}
}
int main()
{
	int i,j,u,v;
	scanf("%i",&n);
	for(i=1;i<n;i++) scanf("%i %i",&u,&v),E[u].pb(v),E[v].pb(u);
	DFSSZ(1,0);
	vector<int> cns;
	for(i=1;i<=n;i++) if(ctr[i]) cns.pb(i);
	for(i:cns)
	{
		for(j:E[i]) if(!ctr[j])
		{
			last=j;
			DFS(j,i,i,j);
			ans.pb(mt(i,last,j));
		}
	}
	vector<tuple<int,int,int> > sol;
	for(i=0;i<ans.size();i++) if(get<1>(ans[i])!=get<2>(ans[i])) sol.pb(ans[i]);
	printf("%i\n",sol.size());
	for(auto p:sol) printf("%i %i %i\n",get<0>(p),get<1>(p),get<2>(p));
	return 0;
}//hello//hello

#include<cstdio>
#include<vector>
using namespace std;
int cnt[200001], n, par;
vector<int> adj[200001];
vector<pair<int, int> > v;
// TO CALCULATE SIZE OF EACH SUBTREE UNDER EVERY NODE
void count(int h, int p) {
    cnt[h]++;
    for (auto it : adj[h]) if (it^p) {
        count(it, h);
        cnt[h] += cnt[it];
    }
}
// TO GET CENTROID OF THE TREE
int ct(int h, int p) {
    for (auto it : adj[h]) if (it^p) {
        if (cnt[it] > n / 2) return ct(it, h);
    }
    par = p;
    return h;
}
vector<pair<int, pair<int, int> > > res;
// TO GET ALL NODES IN A PARTICULAR SUBTREE CONNECTED TO CENTROID
void dfs(int h, int p) {
    for (auto it : adj[h]) if (it^p) {
        dfs(it, h);
    }
    v.push_back({ h,p});
}
// CONVERTING NORMAL TREE INTO CENTROID TREE
void f(int h, int p) {
    v.clear();
    dfs(h, p);
    v.pop_back();
    int t = h;
    for (auto it : v) {
        res.push_back({ p,{t,it.first} });
        res.push_back({ it.first,{it.second,h} });
        t = it.first;
    }
    res.push_back({ p,{t,h} });
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    count(1, 0); //SIZE OF EACH SUBTREE ROOTED AT 1
    int cen = ct(1, 0); //FINDING CENTROID 1
    int cen2 = 0;
    for (auto it : adj[cen]) if (par^it && 2*cnt[it] == n) cen2 = it; //FINDING CENTROID 2 IF EXIST
    for (auto it : adj[cen]) if (it^cen2) f(it, cen); // CONVERTING NORMAL TREE INTO CENTROID TREE FROM CENTROID 1
    for (auto it : adj[cen2]) if (it^cen) f(it, cen2);// CONVERTING NORMAL TREE INTO CENTROID TREE FROM CENTROID 2
    printf("%d\n", res.size());
    for (auto it : res) printf("%d %d %d\n", it.first, it.second.first, it.second.second);
    return 0;
}

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

using namespace std;
using namespace __gnu_pbds;
//
typedef long long lint;

template<typename Key, typename Value>
using hash_map = cc_hash_table<Key, Value>;

const int INF = 0x3f3f3f3f;
const lint INFL = 0x3f3f3f3f3f3f3f3fLL;

template<typename T, typename U> void amin(T &x, U y) { if (y < x) x = y; }
template<typename T, typename U> void amax(T &x, U y) { if (x < y) x = y; }

template<typename Path> struct Centroid {
	vector<vector<int>> adj; vector<int> subtreesize;
	vector<bool> mark; vector<int> outer, layer;
	vector<vector<int>> newid; Path emptypath;
	vector<vector<Path>> paths;
	vector<int> centroids;

	Centroid(int n, Path emptypath): adj(n), subtreesize(n),
		mark(n), outer(n), layer(n), newid(n), emptypath(emptypath),
		paths(n) {}

	template<typename Func>
	void decompose(Func add, bool get_centroids = false, int v = 0, int o = -1, int l = 0) {
		int treesize = dfs1(v, -1);
		int c = dfs2(v, -1, treesize, get_centroids);
		mark[c] = true, outer[c] = o, layer[c] = l;
		paths[c].reserve(treesize);
		dfs3(c, -1, c, add(emptypath, c), add);
		for (int u: adj[c]) if (!mark[u])
			decompose(add, false, u, c, l + 1);
		if (l == 0) dfs1(v, -1);
	}

	int dfs1(int v, int p) {
		subtreesize[v] = 1;
		for (int u: adj[v]) if (u != p && !mark[u])
			subtreesize[v] += dfs1(u, v);
		return subtreesize[v];
	}

	int dfs2(int v, int p, int treesize, bool get_centroids) {
		for (int u: adj[v])
			if (u != p && !mark[u]) {
				if (2 * subtreesize[u] > treesize) {
					return dfs2(u, v, treesize, get_centroids);
				} else if (get_centroids and 2 * subtreesize[u] == treesize) {
					centroids.push_back(u);
				}
			}
		if (get_centroids) {
			centroids.push_back(v);
		}
		return v;
	}

	template<typename Func>
	void dfs3(int v, int p, int c, Path path, Func add) {
		newid[v].push_back(paths[c].size());
		paths[c].push_back(path);
		for (int u: adj[v]) if (u != p && !mark[u])
			dfs3(u, v, c, add(path, u), add);
	}

	int get_id(int v, int c) { return newid[v][layer[c]]; }

	int lco(int a, int b) {
		while (a != b) if (layer[a] > layer[b]) a = outer[a];
					   else b = outer[b];
		return a;
	}

	pair<Path, Path> get_path(int a, int b) {
		int c = lco(a, b);
		return {paths[c][get_id(a, c)], paths[c][get_id(b, c)]};
	}
};

vector<unordered_set<int>> graph;
vector<int> X, Y, Y_, seq;

void doOp(int x, int y, int y_) {
	X.push_back(x);
	Y.push_back(y);
	Y_.push_back(y_);
}

pair<int, int> straighten(int u, int p = -1) {
	vector<pair<int, int>> children;
	for (int v: graph[u]) {
		if (v != p) {
			children.push_back(straighten(v, u));
		}
	}
	if (p == -1) return {-1, -1};
	for (int i = 0; i < (int)children.size(); i++) {
		doOp(i ? children[i - 1].first : p, u, children[i].second);
	}
	return {children.empty() ? u : children[0].second, u};
}

void dfs(int u, int p = -1) {
	seq.push_back(u);
	for (int v: graph[u]) if (v != p) dfs(v, u);
}

void process() {
	for (int i = (int)seq.size() - 1; i >= 2; i--) doOp(seq[i - 2], seq[i - 1], seq.back());
}

void refresh() {
	for (int i = 0; i < (int)X.size(); i++) {
		int x = X[i], y = Y[i], y_ = Y_[i];
		graph[x].erase(y);
		graph[y].erase(x);
		graph[x].insert(y_);
		graph[y_].insert(x);
	}
}

bool solve(int testNumber) {
	int n;
	if (!(cin >> n)) {
		return false;
	}
	Centroid<bool> solver(n, false);
	vector<vector<int>> &G = solver.adj;
	for (int i = 1; i < n; i++) {
		int u, v;
		cin >> u >> v;
		u--, v--;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	solver.decompose([](bool a, bool b) { return a; }, true);
	graph.resize(n);
	for (int i = 0; i < n; i++) {
		graph[i].clear();
		graph[i].insert(G[i].begin(), G[i].end());
	}
	vector<int> &centroids = solver.centroids;
	if ((int)centroids.size() == 2) {
		int u = centroids[0], v = centroids[1];
		graph[u].erase(v);
		graph[v].erase(u);
	}
	X.clear();
	Y.clear();
	Y_.clear();
	for (int c: centroids) {
		straighten(c);
	}
	refresh();
	for (int c: centroids) {
		for (int cc: graph[c]) {
			seq = {c} ;
			dfs(cc, c);
			process();
		}
	}
	int k = (int)X.size();
	printf("%d\n", k);
	for (int i = 0; i < k; i++) {
		printf("%d %d %d\n", X[i] + 1, Y[i] + 1, Y_[i] + 1);
	}
	return true;
}

void init(const char *in = nullptr, const char *out = nullptr) {
	if (in) freopen(in, "r", stdin);
	if (out) freopen(out, "w", stdout);
}

int main() {
	ios_base :: sync_with_stdio(false);
	cin.tie(nullptr);
	init();
	for (int i=1; solve(i); i++);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define N 200005
#define M 400005
typedef pair<int,int>pi;
typedef pair<int,pi>pii;
struct edge
{
    int v,nxt;
}e[M];
int tot,head[N];
void add(int u,int v)
{
    e[tot].v = v;
    e[tot].nxt = head[u];
    head[u] = tot++;
}
vector<int>root;
vector<pii>ans;
bool vis[N];
void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
    root.clear();
    ans.clear();
    memset(vis,0,sizeof(vis));
}
int cnt[N];

void dfs(int p,int pre,int n)
{
   // cout<<p<<endl;
    cnt[p] = 1;
    bool flag = 1;
    for(int i=head[p];~i;i=e[i].nxt){
        int v = e[i].v;
        if(v==pre) continue;
        dfs(v,p,n);
        cnt[p] += cnt[v];
        if(cnt[v] > n/2) flag = 0;
    }
    if(n-cnt[p]>n/2) flag = 0;
    if(flag) root.push_back(p);
}
void sear(int p,int pre,int r,int son,int &c)
{
    for(int i=head[p];~i;i=e[i].nxt){
       int v = e[i].v;
       if(v==pre) continue;
       sear(v,p,r,son,c);
    }
    ans.push_back(pii(r,pi(c,p))); c = p;
    if(p!=son) ans.push_back(pii(p,pi(pre,son)));
}

int main()
{
  int n;
  while(~scanf("%d",&n)){
  init();
  for(int i=0;i<n-1;i++){
    int a,b;
    scanf("%d%d",&a,&b);
    add(a,b);
    add(b,a);
  }
  dfs(1,0,n);
  for(int i=0;i<root.size();i++){
      //vis[root[i]] = 1;
      for(int j=head[root[i]];~j;j=e[j].nxt){
         int v = e[j].v;
         bool leap = 0;
         for(int k=0;k<root.size();k++){
            if(root[k]==v){
                leap = 1;
                break;
            }
         }
         if(leap) continue;
         int pson = v;
         sear(v,root[i],root[i],v,pson);
      }
  }
  printf("%d\n",ans.size());
  int len = ans.size();
  for(int i=0;i<len;i++){
    printf("%d %d %d\n",ans[i].first,ans[i].second.first,ans[i].second.second);
  }
  }
  return 0;
}

/*
СТРОИМ СТЕНУ РАБОТЯГИ!
█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█
█═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═█
█═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═█
█═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═█
█═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═█
█═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═█
█═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═█
█═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═█
█═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═█
█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█
*/
#pragma GCC optimize "-O3"
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cstdio>
#include <numeric>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <list>
#include <cmath>
#include <bitset>
#include <cassert>
#include <queue>
#include <stack>
#include <deque>

using namespace std;
template<typename T1, typename T2>inline void chkmin(T1 &x, T2 y) { if (x > y) x = y; }
template<typename T1, typename T2>inline void chkmax(T1 &x, T2 y) { if (x < y) x = y; }
/** Interface */

inline int readChar();
template <class T = int> inline T readInt();
template <class T> inline void writeInt( T x, char end = 0 );
inline void writeChar( int x );
inline void writeWord( const char *s );

/** Read */

static const int buf_size = 4096;

inline int getChar() {
    static char buf[buf_size];
    static int len = 0, pos = 0;
    if (pos == len) {
        pos = 0, len = fread(buf, 1, buf_size, stdin);
    }
    if (pos == len) {
        return -1;
    }
    return buf[pos++];
}

inline int readChar() {
    int c = getChar();
    while (c <= 32) {
        c = getChar();
    }
    return c;
}

template <class T>
inline T readInt() {
    int s = 1, c = readChar();
    T x = 0;
    if (c == '-')
        s = -1, c = getChar();
    while ('0' <= c && c <= '9')
        x = x * 10 + c - '0', c = getChar();
    return s == 1 ? x : -x;
}

/** Write */

static int write_pos = 0;
static char write_buf[buf_size];

inline void writeChar( int x ) {
    if (write_pos == buf_size)
        fwrite(write_buf, 1, buf_size, stdout), write_pos = 0;
    write_buf[write_pos++] = x;
}

template <class T>
inline void writeInt( T x, char end ) {
    if (x < 0)
        writeChar('-'), x = -x;

    char s[24];
    int n = 0;
    while (x || !n)
        s[n++] = '0' + x % 10, x /= 10;
    while (n--)
        writeChar(s[n]);
    if (end)
        writeChar(end);
}

inline void writeWord( const char *s ) {     while (*s)
writeChar(*s++); }

struct Flusher {
    ~Flusher() {
        if (write_pos)
            fwrite(write_buf, 1, write_pos, stdout), write_pos = 0;
    }
} flusher;

#define sz(c) (int)(c).size()
#define all(c) (c).begin(), (c).end()
#define rall(c) (c).rbegin(), (c).rend()
#define left left228
#define right right228
#define next next228
#define rank rank228
#define prev prev228
#define y1 y1228
const int MAXN = 200228;

int n;
vector<int> g[MAXN];

struct Tree {
    int root;
    int curRoot;
    int parent;
    vector<pair<int, int> > vs;
};

vector<Tree> trees;

struct Triple {
    int x, y, z;
};

vector<Triple> ans;
int c1 = -1, c2 = -1;

int dfs1(int v, int p = -1) {
    int s = 1;
    for (auto h: g[v]) {
        if (h != p) {
            s += dfs1(h, v);
        }
    }
    if (c1 == -1 && s * 2 >= n) {
        c1 = v;
        if (s * 2 == n) {
            c2 = p;
        } else {
            c2 = -1;
        }
    }
    return s;
}

void dfs2(int v, int p) {
    for (auto h: g[v]) {
        if (h != p) {
            dfs2(h, v);
        }
    }
    trees.back().vs.push_back({v, p});
}

int main() {
    n = readInt();
    for (int i = 0; i < n - 1; i++) {
        int x = readInt(), y = readInt();
        x--, y--;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    if (n <= 3) {
        writeInt(0, '\n');
        return 0;
    }
    dfs1(0);
    for (auto h: g[c1]) {
        if (h == c2) {
            continue;
        }
        trees.emplace_back();
        trees.back().root = h;
        trees.back().curRoot = h;
        trees.back().parent = c1;
        dfs2(h, c1);
    }
    if (c2 != -1) {
        for (auto h: g[c2]) {
            if (h == c1) {
                continue;
            }
            trees.emplace_back();
            trees.back().root = h;
            trees.back().curRoot = h;
            trees.back().parent = c2;
            dfs2(h, c2);
        }
    }
    for (auto &tree: trees) {
        for (auto pp: tree.vs) {
            int v = pp.first, p = pp.second;
            if (v == tree.root) {
                break;
            }
            ans.push_back({tree.parent, tree.curRoot, v});
            tree.curRoot = v;
            ans.push_back({v, p, tree.root});
        }
        ans.push_back({tree.parent, tree.curRoot, tree.root});
    }
    writeInt(sz(ans), '\n');
    for (auto t: ans) {
        writeInt(t.x + 1, ' ');
        writeInt(t.y + 1, ' ');
        writeInt(t.z + 1, '\n');
    }
    return 0;
}

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

const int MAX_N = 2e5;

int n;
unordered_set<int> adj[MAX_N + 1];
int sizeOfSubtree[MAX_N + 1];
vector<array<int, 3>> ans;
bool singleCentroid;
int centroid;
pair<int, int> centroids;
int leaf[MAX_N + 1];

void trans(int x, int y, int yp) {
	//cout << "trans " << x << ' ' << y << ' ' << yp << endl;
	adj[x].erase(y);
	adj[y].erase(x);
	adj[x].insert(yp);
	adj[yp].insert(x);
	ans.push_back({x, y, yp});
	//cout << "done" << endl;
}

void calculateSizeOfSubtrees(const int root, const int parent) {
	sizeOfSubtree[root] = 1;
	for (const int adjacent : adj[root]) {
		if (adjacent != parent) {
			calculateSizeOfSubtrees(adjacent, root);
			sizeOfSubtree[root] += sizeOfSubtree[adjacent];
		}
	}
	return;
}

void calculateCentroid() {
	int root = 1;
	bool foundCentroid = false;
	calculateSizeOfSubtrees(root, -1);
	while (not foundCentroid) {
		foundCentroid = true;
		for (const int adjacent : adj[root]) {
			if (sizeOfSubtree[adjacent] * 2 > n) {
				foundCentroid = false;
				sizeOfSubtree[root] = n - sizeOfSubtree[adjacent];
				sizeOfSubtree[adjacent] = n;
				root = adjacent;
				break;
			} else if (sizeOfSubtree[adjacent] * 2 == n) {
				singleCentroid = false;
				centroids = {root, adjacent};
				return;
			}
		}
	}
	singleCentroid = true;
	centroid = root;
	return;
}

void line(int v, int p) {
	unordered_set<int> tmp;
	tmp = adj[v];
	for (int a : tmp)
		if (a != p)
			line(a, v);
	tmp = adj[v];
	int pp = p;
	bool setleaf = false;
	for (int a : tmp) {
		if (a != p) {
			trans(pp, v, leaf[a]);
			pp = a;
			if (not setleaf) {
				leaf[leaf[a]] = v;
				setleaf = true;
			}
		}
	}
	if (not setleaf)
		leaf[v] = v;
}

bool isline(int v, int p) {
	if (adj[v].size() == 1)
		return true;
	else if (adj[v].size() == 2)
		if (*adj[v].begin() != p)
			return isline(*adj[v].begin(), v);
		else
			return isline(*++adj[v].begin(), v);
	else {
		cout << "v: " << v << endl;
		cout << "deg: " << adj[v].size() << endl;
		cout << "p: " << p << endl;
		return false;
	}
}

void star(int v, int p) {
	//cout << "in star " << v << ' ' << p << endl;
	int c = leaf[v];
	//cout << "c: " << c << endl;
	int s = *adj[c].begin();
	//cout << "s: " << s << endl;
	while (s != p) {
		assert(adj[s].size() == 2);
		int a = (*adj[s].begin() == c? *++adj[s].begin() : *adj[s].begin());
		trans(a, s, c);
		s = a;
		//cout << "s: " << endl;
	}
}

bool isStar(int v, int p) {
	for (int a : adj[v])
		if (a != p and adj[a].size() != 1) {
			cout << "a: " << a << endl;
			return false;
		}
	return true;
}

int main() {
	cin >> n;
	for (int i = 1, a, b; i <= n - 1; ++i) {
		cin >> a >> b;
		adj[a].insert(b);
		adj[b].insert(a);
	}
	//cout << "read inputs" << endl;
	calculateCentroid();
	//cout << "calulated centroids" << endl;
	if (singleCentroid)
		centroids = {centroid, 0};
	unordered_set<int> tmp;
	tmp = adj[centroids.first];
	for (int a : tmp)
		if (a != centroids.second)
			line(a, centroids.first);
	//cout << "lined first centroid" << endl;
	tmp = adj[centroids.second];
	for (int a : tmp)
		if (a != centroids.first)
			line(a, centroids.second);
	//cout << "lined second centroid" << endl;
	for (int a : adj[centroids.first])
		if (a != centroids.second and not isline(a, centroids.first)) {
			cout << "centroids.first: " << centroids.first << endl;
			cout << "a: " << a << endl;
			return 0;
		}
	//cout << "first centroid is line" << endl;
	for (int a : adj[centroids.second])
		if (a != centroids.first and not isline(a, centroids.second)) {
			cout << "centroids.second: " << centroids.second << endl;
			cout << "a: " << a << endl;
			return 0;
		}
	//cout << "second centroid is line" << endl;
	tmp = adj[centroids.first];
	for (int a : tmp)
		if (a != centroids.second) {
			//cout << "want to star " << a << endl;
			star(a, centroids.first);
		}
	//cout << "stared first centroid" << endl;
	tmp = adj[centroids.second];
	for (int a : tmp)
		if (a != centroids.first)
			star(a, centroids.second);
	//cout << "stared second centroid" << endl;
	for (int a : adj[centroids.first])
		if (a != centroids.second and not isStar(a, centroids.first)) {
			cout << "centroids.first: " << centroids.first << endl;
			cout << "a: " << a << endl;
			return 0;
		}
	//cout << "first centroid is star" << endl;
	for (int a : adj[centroids.second])
		if (a != centroids.first and not isStar(a, centroids.second)) {
			cout << "centroids.second: " << centroids.second << endl;
			cout << "a: " << a << endl;
			return 0;
		}
	//cout << "second centroid is star" << endl;
	cout << ans.size() << endl;
	for (auto x : ans)
		cout << x[0] << ' ' << x[1] << ' ' << x[2] << endl;
	return 0;
}

#include <bits/stdc++.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define RI(X) scanf("%d", &(X))
#define RII(X, Y) scanf("%d%d", &(X), &(Y))
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))
#define DRI(X) int (X); scanf("%d", &X)
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)
#define RS(X) scanf("%s", (X))
#define CASET int ___T, case_n = 1; scanf("%d ", &___T); while (___T-- > 0)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define PII pair<int,int>
#define VPII vector<pair<int,int> >
#define PLL pair<long long,long long>
#define F first
#define S second
typedef long long LL;
using namespace std;
const int MOD = 1e9+7;
const int SIZE = 2e5+10;
// template end here
VPII res;
vector<int> res2,e[SIZE];
int N,L,R;
int bfs[SIZE],sons[SIZE];
int used[SIZE],tt,tt2,father[SIZE];
int CC,PTR;
void dfs(int x,int lt,int o){
    REP(i,SZ(e[x])){
        int y=e[x][i];
        if(y==lt)continue;
        dfs(y,x,o);
    }
    if(lt!=o&&x!=o){
        if(PTR!=x){
            res.PB(MP(CC,PTR));
            res2.PB(x);
            PTR=x;
        }
        res.PB(MP(x,lt));
        res2.PB(o);
    }
}
void go(int x,int lt){
    CC=x;
    REP(i,SZ(e[x])){
        int y=e[x][i];
        if(y==lt)continue;
        PTR=y;
        dfs(y,x,y);
        if(PTR!=y){
            res.PB(MP(CC,PTR));
            res2.PB(y);
        }
    }
}
void build(int st){
    bfs[0]=st;
    tt2--;
    used[st]=tt2;
    int i=0,j=1;
    for(;i<j;i++){
        int x=bfs[i];
        sons[x]=1;
        REP(k,SZ(e[x])){
            int y=e[x][k];
            if(used[y]==tt||used[y]==tt2)continue;
            father[y]=x;
            used[y]=tt2;
            bfs[j++]=y;
        }
    }
    int num=j;
    for(i=j-1;i>=0;i--){
        int x=bfs[i];
        if(sons[x]*2>=num){
            if(sons[x]*2>num){;
                go(x,x);
                return;
            }
            else{
                int z=father[x];
                go(x,z);
                go(z,x);
                return;
            }
        }
        sons[father[x]]+=sons[x];
    }
}
void init(){
    tt++;
    build(1);
}
int main(){
    RI(N);
    REPP(i,1,N){
        DRII(x,y);
        e[x].PB(y);
        e[y].PB(x);
    }
    init();
    printf("%d\n",SZ(res));
    REP(i,SZ(res))printf("%d %d %d\n",res[i].F,res[i].S,res2[i]);
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using vi = vector<int>;
using db = double;
#define pb push_back
#define fir first
#define sec second

using pii = pair<int,int>;

struct Ope {
	int x, y, z;
};

vector<Ope> sol;

const int mxn = 200006;

int s[mxn];
vi e[mxn];

#define fors(i) for (auto i : e[x]) if (i != p)
int size(int x, int p)
{ s[x] = 1; fors(i) s[x] += size(i, x); return s[x]; }
int core(int x, int p) {
	fors(i) if (s[x] - s[i] < s[i])
		return s[x] -= s[i], s[i] += s[x], core(i, x);
	return x;
}

bool v[mxn];

int n;
set<int> E[mxn];

void ope(int x, int y, int z) {
	sol.pb({x, y, z});
	E[x].erase(y);
	E[y].erase(x);
	E[x].insert(z);
	E[z].insert(x);
}

pii chain(int x, int p) {
	vector<pii> u;
	int o = p;
	fors(i) {
		auto t = chain(i, x);
		u.pb(t);
	}
	int FIR = 0;
	for (auto i : u) {
		if (!FIR)
			FIR = i.sec;
		ope(o, x, i.sec);
		o = i.fir;
	}

	if (FIR == 0)
		FIR = x;

	return {FIR, x};
}

int flower(int x, int p) {
	//cout << x << ' ' << p << endl;
	int y = 0;
	for (auto i : E[x]) if (i != p) {
		y = flower(i, x);
		break;
	}
	if (y) {
		ope(p, x, y);
		return y;
	} else {
		return x;
	}
}

int main() {
	cin >> n;

	for (int i = 1; i < n; ++i) {
		int x, y;
		scanf("%d%d", &x, &y);
		e[x].pb(y);
		e[y].pb(x);
		E[x].insert(y);
		E[y].insert(x);
	}

	size(1, 0);
	vi co;
	int c = core(1, 0);
	co.pb(c);
	v[c] = true;
	for (auto i : e[c]) if (s[i] * 2 == n) {
		v[i] = true;
		co.pb(i);
	}

	for (auto i : co)
		for (auto j : e[i]) if (!v[j]) {
			flower(chain(j, i).fir, i);
		}

	cout << sol.size() << endl;
	for (auto i : sol)
		printf("%d %d %d\n", i.x, i.y, i.z);

	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("O2,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define F first
#define S second
#define pb push_back
#define SZ(x) (ll)(x.size())
#define all(x) x.begin(),x.end()
#define MP make_pair
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pll;
const ll maxn=2e5+10, maxm=2e5+10, lg=61, mod=1e9+7, inf=1e18;

ll n,sz[maxn],par[maxn];
vector<ll> g[maxn];
vector<pair<ll,pll>> ans;
void pfs(ll v=1,ll p=0){ sz[v]=1; for(auto u:g[v])if(u!=p) pfs(u,v), sz[v]+=sz[u]; }
ll V,U,cur;
void dfs(ll v,ll p){
	for(auto u:g[v])if(u!=p) dfs(u,v);
	cout<<V<<' '<<cur<<' '<<v<<endl;
	cur=v;
	if(v==U) swap(v,p);
	cout<<v<<' '<<p<<' '<<U<<endl;
}

int main(){
	ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);

	cin>>n;
	for(int i=1;i<n;i++){
		ll v,u; cin>>v>>u;
		g[v].pb(u), g[u].pb(v);
	}
	pfs();
	vector<ll> cen;
	for(int i=1;i<=n;i++){
		ll mx=n-sz[i];
		for(auto u:g[i])if(sz[u]<sz[i]) mx=max(mx,sz[u]);
		if(mx<=n/2) cen.pb(i);
	}
	cout<<2*(n-SZ(cen))<<endl;
	for(auto v:cen){
		for(auto u:g[v]){
			bool F=1;
			for(auto w:cen)if(u==w) F=0;
			if(F) dfs(cur=U=u,V=v);
		}
	}

	return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <cstdio>
#include <stdlib.h>
#include <stack>
#include <numeric>
#include <bitset>
#include <cctype>
#include <list>
#include <assert.h>
#include <random>
#include <unordered_map>
#include <ctime>
typedef  long long ll;
using namespace std;
#define INF 2147483647
#define infL (1LL<<60)
#define inf (1<<30)
#define inf9 (1000000000)
#define MOD 1000000007
#define EPS 1e-9
#define Gr 9.8
#define PI acos(-1)
#define REP(i,n) for(int (i)=0;(i)<(int)(n);(i)++)
#define REQ(i,n) for(int (i)=1;(i)<=(int)(n);(i)++)
#define lch (rt<<1)
#define rch (rt<<1|1)
#define readmp(n) for(int i=0,u,v;i<n;i++) {scanf("%d%d",&u,&v); mp[u].push_back(v); mp[v].push_back(u);}
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef long double ld;
typedef unsigned int uint;
#define MAX 200125
bool debug = 0;
int n,m,k;
int dx[4] = {0,1,0,-1}, dy[4] = {1,0,-1,0};
string direc="RDLU";
ll ln, lk, lm;
void etp(bool f = 0) {
    puts(f ?"YES" : "NO");
    exit(0);
}

vector<int> mp[MAX];
int sz[MAX];
vector<int> rs;
void dfs(int x, int pa) {
    sz[x]=1;
    bool ok = 1;
    for(int c:mp[x]) if (c!=pa) {
        dfs(c,x);
        sz[x]+=sz[c];
        if (sz[c]+sz[c]>n) ok=0;
    }
    if ((n-sz[x])*2>n) ok =0;
    if (ok) rs.push_back(x);
}
vector<int> vp[MAX];
int R,fa[MAX];
void dfs2(int x, int pa, int D) {
    fa[x]=pa;
    if (D==1) R=x;
    else if(2<D) {
        vp[R].push_back(x);
    }
    for(int  c:mp[x]) if (c!=pa) {
        dfs2(c,x,D+1);
    }
}
vector<pair<int, pii>> ans;
void fmain(int tid) {
    scanf("%d", &n);
    readmp(n-1);
    dfs(1,0);
    if (rs.size()==1) dfs2(rs[0], 0, 0);
    else {
        dfs2(rs[0],rs[1],0);
        dfs2(rs[1],rs[0],0);
    }
    REQ(i,n) if (!vp[i].empty()) {
        int cur = i;
        for(int p : vp[i]) {
            ans.push_back({fa[i], {cur, p}});
            ans.push_back({p,{fa[p], i}});
            cur=p;
        }
        ans.push_back({fa[i],{cur,i}});
    }
    printf("%d\n",(int)ans.size());
    for(auto p : ans) {
        printf("%d %d %d\n",p.first,p.second.first,p.second.second);
    }
}
int main() {
    int t=1;
//    scanf("%d", &t);
    REQ(i,t) {
        fmain(i);
    }
    return 0;
}

// {{{
//#pragma GCC optimize("O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")

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

#define VARGS_(_4, _3, _2, _1, N, ...) N
#define VARGS(...) VARGS_(__VA_ARGS__, 4, 3, 2, 1)
#define CONCAT_(a, b) a##b
#define CONCAT(a, b) CONCAT_(a, b)
#define FOR_1(x) for (auto& x)
#define FOR_2(i, n) for (auto i = remove_reference_t<decltype(n)>{0}; i < (n); ++i)
#define FOR_3(i, b, e) for (auto i = remove_reference_t<decltype(e)>{b}; i < (e); ++i)
#define FOR_4(i, b, e, s) for (auto i = remove_reference_t<decltype(e)>{b}; i < (e); i += s)
#define FORD_2(i, n) for (auto i = (n) - 1; i >= 0; --i)
#define FORD_3(i, b, e) for (auto i = remove_reference_t<decltype(b)>{(e) - 1}; i >= (b); --i)
#define FORD_4(i, b, e, s) for (auto i = remove_reference_t<decltype(b)>{(e) - 1}; i >= (b); i -= s)
#define FOR(...) CONCAT(FOR_, VARGS(__VA_ARGS__))(__VA_ARGS__)
#define FORD(...) CONCAT(FORD_, VARGS(__VA_ARGS__))(__VA_ARGS__)
#define B begin()
#define E end()
#define RB rbegin()
#define RE rend()
#define A(x) std::begin(x), std::end(x)
#define RA(x) std::rbegin(x), std::rend(x)
#define RANGE(x, b, e) (std::begin(x) + (b)), (std::begin(x) + (e))
#define MP make_pair
#define MT make_tuple
#define FS first
#define ND second
#define G1 get<0>
#define G2 get<1>
#define G3 get<2>
#define G4 get<3>
#define G5 get<4>
#define PB push_back
#define PP pop_back
#define PF push_front
#define FF pop_front
#define RS resize
#define INF(T) numeric_limits<T>::max()
#define L0(_expr) [&]() { return _expr; }
#define L1(_expr) [&](auto&& _1) { return _expr; }
#define L2(_expr) [&](auto&& _1, auto&& _2) { return _expr; }
#define _ CONCAT(_unused_, __COUNTER__)
#define MIN min_element
#define MAX max_element
#define SUM accumulate

using namespace std;

using LL = long long; using LD = long double; using ULL = unsigned long long;
template<class T1,class T2> using P = pair<T1,T2>;
using PII = P<int,int>; using PLL = P<LL,LL>; using PLD = P<LD,LD>;
template<class T> using V = vector<T>;
using VI = V<int>; using VLL = V<LL>; using VLD = V<LD>; using VB = V<bool>; using VS = V<string>;
template<class T,class Comp=greater<T>> using PQ = priority_queue<T,V<T>,Comp>;

template<class T> int sz(const T& x) { return (int)size(x); }
template<class T> bool amin(T& a, const T& b) { if (b < a) { a = b; return true; } return false; }
template<class T> bool amax(T& a, const T& b) { if (b > a) { a = b; return true; } return false; }
/* find_by_order(k) - k'th largest counting from 0;
   order_of_key(k) - number of items strictly smaller than k;
   join(other), split(k, other) - all keys in other greater than in *(this). */
template<class K,class V,class Comp=less<K>> using ordered_map = __gnu_pbds::tree<K,V,Comp,
      __gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;
template<class T,class Comp=less<T>> using ordered_set = ordered_map<T,__gnu_pbds::null_type,Comp>;
const size_t rseed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
mt19937 _rnd(rseed); template<class T> T randint(T lo, T hi) { return uniform_int_distribution<T>{lo,hi}(_rnd); }
struct random_hash {
  template<class T1,class T2> size_t operator()(const P<T1,T2>& key) const noexcept {
  size_t h1 = hash<T1>{}(key.FS), h2 = hash<T2>{}(key.ND);
  return (*this)(h1 + 0x517cc1b7 + (h2 << 6) + (h2 >> 2)); }
  template<class T> size_t operator()(const T& key) const noexcept {
  size_t h = hash<T>{}(key); return h + (h << 4) + 0x9e3779b9 + (rseed << 6) + (rseed >> 2); }};
template<class K,class V> using hash_map = __gnu_pbds::gp_hash_table<K,V,random_hash>;
template<class T> using hash_set = hash_map<T,__gnu_pbds::null_type>;

string _ignore; struct ioctx { string sep; ostream* os; istream* is; bool nl; } _ioctx;
template<class TH> void out(const TH& h) { if (!exchange(_ioctx.nl, false)) *_ioctx.os << _ioctx.sep; *_ioctx.os << h; }
template<class TH,class...TA> void out(const TH& h, const TA&... a) { out(h); out(a...); }
void outln() { *_ioctx.os << '\n'; _ioctx.nl = true; }
template<class...TA> void outln(const TA&... a) { out(a...); outln(); }
template<class TH> void in(TH& h) { *_ioctx.is >> h; }
template<class TH,class...TA> void in(TH& h, TA&... a) { in(h); in(a...); }
template<class...TA> void EXIT(const TA&... a) { outln(a...); exit(0); }
#ifdef SPONGE
template<class...TA> void dbg(const TA&... a)
{ auto ctx = exchange(_ioctx, {" ", &cerr, &cin, true}); cerr << "\033[1;33m"; outln(a...); cerr << "\033[0m"; _ioctx = ctx; }
#else
#define dbg(...)
#endif
struct _upgrade_io { _upgrade_io(bool ok) { _ioctx = {" ", &cout, &cin, true};
  if (ok) { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cout.precision(15); cout.setf(ios::fixed, ios::floatfield); }}
} _upgrade_io(true);
/* bitset: _Find_first(), _Find_next(i); builtins: __builtin_popcount, __builtin_parity, __builtin_clz, __builtin_ctz */
// }}}

int n;
V<VI> tree;
VI tsz, par, post_order;
int centroid[2];
V<array<int,3>> ans;

void dfs(int u)
{
  tsz[u] = 1;
  FOR(v : tree[u]) if (v != par[u]) {
    par[v] = u;
    dfs(v);
    tsz[u] += tsz[v];
  }
  post_order.PB(u);
}

int main()
{
  in(n);
  tree.RS(n + 1);
  FOR(_, n - 1) {
    int u, v;
    in(u, v);
    tree[u].PB(v);
    tree[v].PB(u);
  }

  tsz.RS(n + 1);
  par.RS(n + 1);
  dfs(1);

  int k = 0;
  FOR(u, 1, n + 1) {
    bool ok = true;
    FOR(v : tree[u]) {
      int s = (par[u] == v ? n - tsz[u] : tsz[v]);
      ok &= (2 * s <= n);
      if (!ok) break;
    }
    if (ok) centroid[k++] = u;
  }

  FOR(i, k) if (centroid[i]) {
    FOR(r : tree[centroid[i]]) if (r != centroid[1 - i]) {
      post_order.clear();
      par[r] = centroid[i];
      dfs(r);
      if (sz(post_order) == 1) continue;
      ans.PB({centroid[i], r, post_order[0]});
      FOR(j, sz(post_order) - 1) {
        ans.PB({post_order[j], par[post_order[j]], r});
        ans.PB({centroid[i], post_order[j], post_order[j + 1]});
      }
    }
  }

  outln(sz(ans));
  FOR(a : ans) {
    FOR(i, 3) out(a[i]);
    outln();
  }
}

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

int N;
vector<vector<int> > adj;
vector<int> sz;

void getSz(int u, int p) {
	sz[u] = 1;
	for(int i = 0; i < adj[u].size(); i++) {
		int v = adj[u][i];
		if(v == p) continue;
		getSz(v, u);
		sz[u] += sz[v];
	}
}

int getCent(int u, int p, int tot) {
	for(int i = 0; i < adj[u].size(); i++) {
		int v = adj[u][i];
		if(v == p) continue;
		if(sz[v] > tot/2) return getCent(v, u, tot);
	}
	return u;
}

int root, del = -1, cur;

struct Info {
    int x, y1, y2;
};
vector<Info> ans;

void dfs(int u, int p, int c) {
    for(int i = 0; i < adj[u].size(); i++) {
        int v = adj[u][i];
        if(v == p || v == del) continue;
        if(c == -1) cur = v;
        dfs(v, u, c == -1? v : c);
        if(c == -1) ans.push_back({root, cur, v});
    }
    if(c == -1 || c == u) return;
    ans.push_back({root, cur, u});
    ans.push_back({u, p, c});
    cur = u;
}

int main() {
    scanf("%d", &N);
    adj.resize(N);
    for(int i = 0; i < N - 1; i++) {
        int u, v; scanf("%d %d", &u, &v);
        u--; v--;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    sz = vector<int>(N, 0);
    getSz(0, -1);
    int cent1 = getCent(0, -1, sz[0]);
    getSz(cent1, -1);

    int cent2 = -1;
    for(int i = 0; i < adj[cent1].size(); i++) {
        int v = adj[cent1][i];
        if(N % 2 == 0 && sz[v] == N / 2) {
            cent2 = v;
            break;
        }
    }

    if(cent2 == -1) {
        root = cent1;
        dfs(cent1, -1, -1);
    }
    else {
        root = cent1;
        del = cent2;
        dfs(cent1, -1, -1);
        root = cent2;
        del = cent1;
        dfs(cent2, -1, -1);
    }

    printf("%d\n", ans.size());
    for(int i = 0; i < ans.size(); i++) {
        printf("%d %d %d\n", ans[i].x + 1, ans[i].y1 + 1, ans[i].y2 + 1);
    }
}

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define ld long double
#define pii pair<int,int>
int const M=2e5+10,M2=1000+10,inf=1e9+10,mod=1e9+7;
vector<int>adj[M];
int zt[M],n;
vector<pair<pii,int> >ans;
vector<int>cen;
vector<int>tmp;
pii last;
void pre_dfs(int v,int l)
{
	bool flag=0;
	zt[v]=1;
	for(int i=0;i<adj[v].size();i++)
	{
		int u=adj[v][i];
		if(u!=l){
			pre_dfs(u,v);
			zt[v]+=zt[u];
			if(zt[u]>n/2)flag=1;
		}
	}
	int t=n-zt[v];
	if(t>n/2)flag=1;
	if(!flag)cen.pb(v);
}
void dfs(int v,int l,int root)
{
	for(int i=0;i<adj[v].size();i++)
	{
		int u=adj[v][i];
		if(u!=l)dfs(u,v,root);
	}
	if(v!=root)
	{
		ans.pb(mp(last,v));
		last=mp(v,l);
	}
	tmp.pb(v);
}
int32_t main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n-1;i++)
	{
		int a,b;
		cin>>a>>b;
		adj[a].pb(b);
		adj[b].pb(a);
	}
	pre_dfs(1,0);
	int good1=cen[0];
	int good2=0;
	if(cen.size()>1)good2=cen[1];
	for(int i=0;i<cen.size();i++)
	{
		int v=cen[i];
		//cout<<v<<"**************"<<endl;
		for(int i=0;i<adj[v].size();i++)
		{
			int u=adj[v][i];
			//cout<<u<<endl;
			last=mp(v,u);
			if(u!=good1 && u!=good2){
				tmp.clear();
				tmp.pb(v);
				dfs(u,v,u);
				//cout<<tmp.size()<<" "<<u<<endl;
				for(int j=(int)tmp.size()-1;j>=1;j--)
				{
					//if(u==3)cout<<tmp[j]<<" "<<tmp[j-1]<<"********"<<endl;
					ans.pb(mp(mp(tmp[j-1],tmp[j]),tmp.back()));
				}
			}
		}
	}
	cout<<ans.size()<<"\n";
	for(int i=0;i<ans.size();i++)cout<<ans[i].F.F<<" "<<ans[i].F.S<<" "<<ans[i].S<<"\n";
}

/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author
 */

#ifndef MAJK_LIB
#define MAJK_LIB

#include <vector>
#include <stack>
#include <iostream>
#include <unordered_map>
#include <map>
#include <iomanip>
#include <set>
#include <functional>
#include <fstream>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <string>
#include <sstream>
#include <queue>
#include <bitset>
using namespace std;

#define x first
#define y second
constexpr int MOD = 1000000007;

typedef std::pair<int,int> pii;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int ui;

template<typename T, typename F> T foo(T t, T g, F f) {
	return t;
}

template <typename T, typename U> std::istream&operator>>(std::istream&i, pair<T,U>&p) {i >> p.x >> p.y; return i;}
template<typename T>std::istream&operator>>(std::istream&i,vector<T>&t) {for(auto&v:t){i>>v;}return i;}
template<typename T>std::ostream&operator<<(std::ostream&o,const vector<T>&t) {for(size_t i=0;i<t.size();++i){o<<t[i]<<" \n"[i == t.size()-1];}return o;}
template<typename T> using minheap = priority_queue<T, vector<T>, greater<T>>;
template<typename T> using maxheap = priority_queue<T, vector<T>, less<T>>;
auto fraclt = [](const pii&a,const pii&b) { return (ll)a.x * b.y < (ll)b.x * a.y; };
struct cmpfrac { bool operator()(const pii&a,const pii&b)const { return (ll)a.x * b.y < (ll)b.x * a.y; }};
template <typename T> bool in(T a, T b, T c) { return a <= b && b < c; }
int logceil(ll x) {int b=0;while(x){x>>=1;++b;}return b;}

namespace std {
    template<typename T,typename U>struct hash<pair<T,U>>{hash<T>t;hash<U>u;size_t operator()(const pair<T,U>&p)const{return t(p.x)^(u(p.y)<<7);}};
}
template<typename T,typename F>T bsh(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){l=m+1;r=m;}else{h=m-1;}}return r;}
template<typename T,typename F>T bsl(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){h=m-1;r=m;}else{l=m+1;}}return r;}
template<typename T> T gcd(T a,T b) { if (a<b) swap(a,b); return b?gcd(b,a%b):a; }

template<typename T>class vector2:public vector<vector<T>>{public:vector2(){} vector2(size_t a,size_t b,T t=T()):vector<vector<T>>(a,vector<T>(b,t)){}};
template<typename T>class vector3:public vector<vector<vector<T>>>{public:vector3(){} vector3(size_t a,size_t b,size_t c,T t=T()):vector<vector<vector<T>>>(a,vector<vector<T>>(b,vector<T>(c,t))){}};
template <typename T> struct bounded_priority_queue {
	inline bounded_priority_queue(ui X) : A(X), B(0) {}
	inline void push(ui L, T V) { B = max(B, L); A[L].push(V); }
	inline const T &top() const { return A[B].front(); }
	inline void pop() { A[B].pop(); while (B > 0 && A[B].empty()) --B; }
	inline bool empty() const { return A[B].empty(); }
	inline void clear() { B = 0; for (auto &a: A) a = queue<T>(); }
private:
	vector<queue<T>> A; ui B;
};

#endif
// #include "../l/mod.h"

class TaskC {
public:
	vector<vector<int>> E;
	int N;

	vector<int> S, P;
	vector<pair<int,pii>> Ans;

	int size(int u, int par) {
		int s = 1;
		P[u] = par;
		for (int v:E[u]) {
			if (v!=par) s+=size(v,u);
		}
		return S[u] = s;
	}

	void do_solve(int x, int y, int u, int par, vector<int> &path) {
		if (E[u].size() == 1) {
			Ans.push_back({x,{y,u}});
		} else {
			for (int v:E[u]) {
				if (v != par) {
					do_solve(x,y,v,u,path);
					x=v;
					y=u;
				}
			}
		}
		path.push_back(u);

	}

    void solve(istream& cin, ostream& cout) {
		cin >> N;
		E.clear();
		E.resize(N);
		for (int i = 0; i < N - 1; ++i) {
			int a,b;cin >> a >> b; --a; --b;
			E[a].push_back(b);
			E[b].push_back(a);
		}

		S.resize(N); P.resize(N);

		size(0, -1);

		vector<bool> centroid(N, false);
		for (int i = 0; i < N; ++i) {
			int s = N - S[i];
			for (int v:E[i]) {
				if (v!=P[i]) {
					s = max(s, S[v]);
				}
			}
			if (s*2 <= N) centroid[i] = true;
		}

		for (int i = 0; i < N; ++i) {
			if (centroid[i]) {
				for (int v:E[i]) {
					if (!centroid[v]) {
						vector<int> P{i};
						do_solve(i, v, v, i, P);
						int q = P.size();
						for (int j = q-4; j >= 0; j--) {
							Ans.push_back({P[j], {P[j+1], P[q-2]}});
						}
					}
				}
			}
		}

		cout << Ans.size() << endl;
		for (auto a:Ans) {
			cout << a.x+1 << ' ' << a.y.x+1 << ' ' << a.y.y+1 << '\n';
		}
    }
};

int main() {
	ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	TaskC solver;
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
const int N=200010;
vector<int> v[N],c[N],rt;
int n,siz[N],fa[N],dep[N];
vector<pair<int,pair<int,int> > > ans;
void dfs1(int np,int fath)
{
	bool isrt=1;
	siz[np]=1;
	for(int x:v[np])
	{
		if(x==fath)continue;
		dfs1(x,np);
		siz[np]+=siz[x];
		if(siz[x]>(n>>1))isrt=0;
	}
	if(n-siz[np]>(n>>1))isrt=0;
	if(isrt)rt.push_back(np);
}
int stk[N],top;
void dfs2(int np,int fath)
{
	fa[np]=fath;
	stk[top++]=np;
	if(dep[np]>=3)
		c[stk[1]].push_back(np);
	for(int x:v[np])
	{
		if(x==fath)continue;
		dep[x]=dep[np]+1;
		dfs2(x,np);
	}
	top--;
}
int main()
{
	scanf("%d",&n);
	for(int i=1,ti,tj;i<n;i++)
	{
		scanf("%d%d",&ti,&tj);
		v[ti].push_back(tj);
		v[tj].push_back(ti);
	}
	dfs1(1,0);
	if(rt.size()==1)
		dfs2(rt[0],0);
	else
		dfs2(rt[0],rt[1]),dfs2(rt[1],rt[0]);
	for(int i=1;i<=n;i++)if(c[i].size())
	{
		int cur=i;
		for(int p:c[i])
		{
			ans.push_back(make_pair(fa[i],make_pair(cur,p))),ans.push_back(make_pair(p,make_pair(fa[p],i)));
			cur=p;
		}
		ans.push_back(make_pair(fa[i],make_pair(cur,i)));
	}
	printf("%d\n",ans.size());
	for(int i=0;i<ans.size();i++)
		printf("%d %d %d\n",ans[i].first,ans[i].second.first,ans[i].second.second);
	return 0;
}

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i = a; i < b; ++i)
#define all(c) c.begin(), c.end()
#define gmax(x,y) x=max(x,y)
#define gmin(x,y) x=min(x,y)
#define gadd(x,y) x=add(x,y)
#define gmul(x,y) x=mul(x,y)
using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
typedef vector<int> vi;

const int N = 2e5 + 5;
vector<int> g[N];
int sz[N], p[N], fir[N];

void init(int x = 1,int first_val = -1,int par = 0){
	sz[x] = 1;
	if(p[x] != -1 && first_val == -1)first_val = x;
	p[x] = par;
	fir[x] = first_val;
	for(int v:g[x]){
		if(v == par || p[v] == -1)continue;
		init(v,first_val,x);
		sz[x] += sz[v];
	}
}

int n;

void find_cent(int u){
	int nxt = -1;
	for(int v: g[u]){
		if(v == p[u])continue;
		if(nxt == -1 || sz[nxt] < sz[v])nxt = v;
	}
	if(nxt == -1)return;
	int val = n - sz[u];
	if(max(sz[nxt],val) <= n/2){
		p[u] = -1;
	}
	find_cent(nxt);
}

int cur[N], c[N];

int main(){
	cin.tie(0);
	cout.tie(0);
	ios_base::sync_with_stdio(0);
	cin >> n;
	rep(i,0,n-1){
		int x,y;
		cin >> x >> y;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	init();
	find_cent(1);
	rep(i,1,n+1){
		if(p[i] == -1){
			init(i,-1,-1);
			for(int v:g[i]){
				if(p[v] == -1)continue;
				cur[v] = v;
				c[v] = i;
			}
		}
	}

	vector<array<int,3>> v;

	rep(i,1,n+1){
		if(p[i] != -1 && fir[i] != i){
			int cent = c[fir[i]];
			v.emplace_back(array<int,3>{cent,cur[fir[i]],i});
			cur[fir[i]] = i;
			v.emplace_back(array<int,3>{i,p[i],fir[i]});
		}
	}

	// reconnect
	rep(i,1,n+1){
		if(fir[i]	== i){
			int cent = c[fir[i]];
			v.emplace_back(array<int,3>{cent,cur[i],i});
		}
	}

	cout << v.size() << '\n';
	rep(i,0,v.size()){
		cout << v[i][0] << ' ' << v[i][1] << ' ' << v[i][2] << '\n';
	}
}

#include<bits/stdc++.h>
using namespace std;
const int maxn=400000+10;
struct node
{
	int x,y,z;
}ans[maxn];
int sz[maxn],root,rt,rt2,n,tot,mx,cur,now;
vector<int> g[maxn];
void dfs(int p,int fa)
{
	sz[p]=1;int val=0;
	for(int i=0;i<g[p].size();i++)
	{
		int v=g[p][i];if(v==fa) continue;
		dfs(v,p);val=max(val,sz[v]);
		sz[p]+=sz[v];
	}
	val=max(val,n-sz[p]);
	if(val<mx)
	{
		mx=val;
		rt=p;
	}
}
void dfs2(int p,int fa)
{
	if(p!=now)
	{
		ans[++tot]=(node){root,cur,p};
		ans[++tot]=(node){p,fa,now};
		cur=p;
	}
	for(int i=0;i<g[p].size();i++)
	{
		int v=g[p][i];
		if(v==fa) continue;
		dfs2(v,p);
	}
}
void work()
{
	root=rt;
	for(int i=0;i<g[rt].size();i++)
	{
		int v=g[rt][i];
		if(v!=rt2)
		{
			now=cur=v;
			dfs2(v,rt);
			ans[++tot]=(node){rt,cur,v};
		}
	}
	root=rt2;
	for(int i=0;i<g[rt2].size();i++)
	{
		int v=g[rt2][i];
		if(v!=rt)
		{
			now=cur=v;
			dfs2(v,rt2);
			ans[++tot]=(node){rt2,cur,v};
		}
	}
}
int main()
{
	//freopen("test.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		int x,y;scanf("%d%d",&x,&y);
		g[x].push_back(y);
		g[y].push_back(x);
	}
	mx=n+1;
	dfs(1,0);dfs(rt,0);
	for(int i=0;i<g[rt].size();i++)
	{
		int v=g[rt][i];
		if(sz[v]>=n-sz[v]) rt2=v;
	}
	work();
	printf("%d\n",tot);
	for(int i=1;i<=tot;i++)
		printf("%d %d %d\n",ans[i].x,ans[i].y,ans[i].z);
}

#ifndef __clang__
#pragma GCC optimize "-O3"
#pragma GCC target "tune=native"
#endif
#include <stdio.h>
#include <bits/stdc++.h>

#define DESTRUCT2(p, a, b)                      \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);

#define DESTRUCT3(p, a, b, c)                   \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);                           \
  auto c = get<2>(p);

#define DESTRUCT4(p, a, b, c, d)                \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);                           \
  auto c = get<2>(p);                           \
  auto d = get<3>(p);

#define FOR(i, n)     for(lli i = 0; i < (lli)(n); ++i)
#define FORU(i, j, k) for(lli i = (j); i <= (lli)(k); ++i)
#define FORD(i, j, k) for(lli i = (j); i >= (lli)(k); --i)

#define SQ(x) ((x)*(x))

#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define eb emplace_back

using namespace std;

template<typename... As>
struct tpl : public std::tuple<As...> {
  using std::tuple<As...>::tuple;
  tpl(std::tuple<As...> const& b) { std::tuple<As...>::operator=(b); }

  template<typename T = tuple<As...> >
  typename tuple_element<0, T>::type const&
  x() const { return get<0>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<0, T>::type&
  x() { return get<0>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<1, T>::type const&
  y() const { return get<1>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<1, T>::type&
  y() { return get<1>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<2, T>::type const&
  z() const { return get<2>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<2, T>::type&
  z() { return get<2>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<3, T>::type const&
  w() const { return get<3>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<3, T>::type&
  w() { return get<3>(*this); }
};

using lli   = long long int;
using llu   = long long unsigned;

using pii   = tpl<lli, lli>;
using piii  = tpl<lli, lli, lli>;
using piiii = tpl<lli, lli, lli, lli>;
using vi    = vector<lli>;
using vii   = vector<pii>;
using viii  = vector<piii>;
using vvi   = vector<vi>;
using vvii  = vector<vii>;
using vviii = vector<viii>;

template<class T>
using min_queue = priority_queue<T, vector<T>, greater<T> >;
template<class T>
using max_queue = priority_queue<T>;

template<size_t... I>
struct my_index_sequence {
  using type = my_index_sequence;
  static constexpr array<size_t, sizeof...(I)> value = { {I...} };
};

namespace my_index_sequence_detail {
  template<typename I, typename J> struct concat;
  template<size_t... I, size_t... J>
  struct concat<my_index_sequence<I...>, my_index_sequence<J...> > :
    my_index_sequence<I..., (sizeof...(I)+J)...> { };
  template<size_t N> struct make_index_sequence :
    concat<typename make_index_sequence<N/2>::type, typename make_index_sequence<N-N/2>::type>::type { };
  template <> struct make_index_sequence<0> : my_index_sequence<>{};
  template <> struct make_index_sequence<1> : my_index_sequence<0>{};
}

template<class... A>
using my_index_sequence_for = typename my_index_sequence_detail::make_index_sequence<sizeof...(A)>::type;

template<class T, size_t... I>
void print_tuple(ostream& s, T const& a, my_index_sequence<I...>){
  using swallow = int[];
  (void)swallow{0, (void(s << (I == 0? "" : ", ") << get<I>(a)), 0)...};
}

template<class T>
ostream& print_collection(ostream& s, T const& a);
template<class... A>
ostream& operator<<(ostream& s, tpl<A...> const& a);
template<class... A>
ostream& operator<<(ostream& s, tuple<A...> const& a);
template<class A, class B>
ostream& operator<<(ostream& s, pair<A, B> const& a);

template<class T, size_t I>
ostream& operator<<(ostream& s, array<T, I> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, vector<T> const& a) { return print_collection(s, a); }
template<class T, class U>
ostream& operator<<(ostream& s, multimap<T, U> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, multiset<T> const& a) { return print_collection(s, a); }
template<class T, class U>
ostream& operator<<(ostream& s, map<T, U> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, set<T> const& a) { return print_collection(s, a); }

template<class T>
ostream& print_collection(ostream& s, T const& a){
  s << '[';
  for(auto it = begin(a); it != end(a); ++it){
    s << *it;
    if(it != prev(end(a))) s << " ";
  }
  return s << ']';
}

template<class... A>
ostream& operator<<(ostream& s, tpl<A...> const& a){
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}

template<class... A>
ostream& operator<<(ostream& s, tuple<A...> const& a){
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}

template<class A, class B>
ostream& operator<<(ostream& s, pair<A, B> const& a){
  return s << "(" << get<0>(a) << ", " << get<1>(a) << ")";
}

namespace std {
  namespace {
    template <class T>
    inline void hash_combine(size_t& seed, T const& v) {
      seed ^= hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
    }
    template <class Tuple, size_t Index = tuple_size<Tuple>::value - 1>
    struct HashValueImpl {
      static void apply(size_t& seed, Tuple const& tuple) {
        HashValueImpl<Tuple, Index-1>::apply(seed, tuple);
        hash_combine(seed, get<Index>(tuple));
      }
    };
    template <class Tuple>
    struct HashValueImpl<Tuple, 0> {
      static void apply(size_t& seed, Tuple const& tuple) {
        hash_combine(seed, get<0>(tuple));
      }
    };
  }
  template <typename ... TT>
  struct hash<tuple<TT...>> {
    size_t operator()(tuple<TT...> const& tt) const {
      size_t seed = 0;
      HashValueImpl<tuple<TT...> >::apply(seed, tt);
      return seed;
    }
  };
  template <typename ... TT>
  struct hash<tpl<TT...>> {
    size_t operator()(tpl<TT...> const& tt) const {
      size_t seed = 0;
      HashValueImpl<tuple<TT...> >::apply(seed, tt);
      return seed;
    }
  };
}

//------------------------------------------------------------------------------

void test(lli n, vii ES, vector<tpl<lli,lli,lli>> ans) {
  vector<set<lli>> G(n);
  for(auto const &p :ES) {
    lli u,v; tie(u,v) = p;
    G[u].insert(v);
    G[v].insert(u);
  }
  for(auto const& p : ans) {
    lli x,y,z; tie(x,y,z) = p;
    assert(G[x].count(y));
    assert(G[y].count(x));
    function<lli(lli,lli)> dfs = [&](lli i, lli p) {
      lli sz=1;
      for(lli j : G[i]) if(j!=p) {
          sz+=dfs(j,i);
        }
      return sz;
    };
    lli szx = dfs(x,y);
    lli szy = dfs(y,x);
    assert(szx>szy);
    G[x].erase(y); G[y].erase(x);
    assert(!G[z].count(x));
    assert(!G[x].count(z));
    G[x].insert(z); G[z].insert(x);
  }
  // lli r=0;
  // function<void(lli,lli,lli,lli)> dfs = [&](lli i0, lli i, lli p, lli d) {
  //   r += d*d;
  //   for(lli j : G[i]) if(j!=p) {
  //       dfs(i0,j,i,d+1);
  //     }
  // };
  // FOR(i,n) dfs(i,i,-1,0);
  // cerr << r << endl;
}

int main(){
  ios::sync_with_stdio(0); cin.tie(0);
  lli n; cin>>n;
  vvi G(n);
  vii ES;
  FOR(i,n-1) {
    lli u,v;
    cin>>u>>v;
    --u; --v;
    // u = i+1; v = i;
    ES.pb(mt(u,v));
    G[u].pb(v);
    G[v].pb(u);
  }

  vi  A(n,0);
  vi  CP(n,-1);
  vi  DP(n,-1);
  lli root;
  vi pairWith(n,-1);
  FOR(l,100){
    vi E = A;
    vi P(n);
    vi S(n,1);
    function<void(vi&, lli,lli)> dfs0 = [&](vi& C, lli i,lli p){
      E[i]=1; P[i]=p; C.pb(i);
      for(lli j : G[i]) if(!A[j] && j!=p) {
          dfs0(C,j,i);
          S[i]+=S[j];
        }
    };
    vi C;
    FOR(i,n) if(!E[i]) {
      C.clear();
      dfs0(C, i, -1);
      auto f = [&](lli j){
        lli r=0;
        for(auto k : G[j]) if(!A[k] && k!=P[j]) r=max<lli>(r,S[k]);
        r=max<lli>(r,S[i]-S[j]);
        return r;
      };
      vi centroids; lli best=1<<30;
      for(lli j : C) {
        lli v=f(j);
        if(v<best) { centroids.clear(); best=v; }
        if(v==best) centroids.pb(j);
      }
      assert(centroids.size()>=1);
      assert(centroids.size()<=2);
      for(lli j:centroids) A[j]=1;
      if(centroids.size() == 2) {
        pairWith[centroids[0]]=centroids[1];
        pairWith[centroids[1]]=centroids[0];
        CP[centroids[1]]=-1;
      }
      if(CP[centroids[0]]==-1) root=centroids[0];
      function<void(lli,lli,lli,lli)> dfs1 = [&](lli k, lli kk, lli i, lli p){
        if(i!=k) {CP[i]=k;DP[i]=kk;}
        for(lli j : G[i]) if(!A[j] && j!=p) {
            dfs1(k,(kk==-1?j:kk),j,i);
          }
      };
      if(centroids.size() == 1) dfs1(centroids[0],-1,centroids[0],-1);
      else {
        dfs1(centroids[0],-1,centroids[0],centroids[1]);
        dfs1(centroids[1],-1,centroids[1],centroids[0]);
      }
    }
    FOR(i,n) if(!A[i]) goto l_beg;
    break;
  l_beg:;
  }

  vvi H(n); FOR(i,n) if(CP[i]!=-1) H[CP[i]].pb(i);
  vector<tuple<int,int,int>> ans;

  function<void(int,int)> solve = [&](int i, int rt) {
    int to=i;
    function<void(int,int)> dfs = [&](int j, int p) {
      for(int k : G[j]) if(k!=p) {
          dfs(k,j);
        }
      if(p!=rt && p!=i) {
        ans.pb(mt(rt,to,j));
        ans.pb(mt(j,p,i));
        to=j;
      }
    };
    dfs(i,rt);
    if(to!=i) ans.pb(mt(rt,to,i));
  };

  for(int i:G[root]) if(i!=pairWith[root]) solve(i,root);
  if(pairWith[root]==-1) {
  }else{
    for(int i:G[pairWith[root]]) if(i!=root) solve(i,pairWith[root]);
  }
  cout << ans.size() << endl;
  for(auto const& p:ans) {
    int x,y,z; tie(x,y,z) = p;
    cout << x+1 << " " << y+1 << " " << z+1 << '\n';
  }
  cout << flush;

  return 0;
}

#include <bits/stdc++.h>

using namespace std;
const int c=200002;
int n, f[c], rf[c], h, l, ki, ut;
vector<int> sz[c];
vector<pair<int, pair<int, int> > > sol;
bool v1[c], v2[c], cen[c];
void add(int x, int y1, int y2) {
    sol.push_back({x, {y1, y2}});
}
void dfs1(int a) {
    v1[a]=true, rf[a]=1;
    int maxi=0;
    for (int x:sz[a]) {
        if (!v1[x]) {
            dfs1(x);
            maxi=max(maxi, rf[x]);
            rf[a]+=rf[x];
        }
    }
    if (rf[a]>=h && n-maxi>=h) {
        cen[a]=1;
        v2[a]=1;
    }
}
void dfs3(int a) {
    v2[a]=true;
    for (int x:sz[a]) {
        if (!v2[x]) {
            //f[x]=a;
            dfs3(x);
            add(l, ut, x);
            add(x, a, ki);
            ut=x;
        }
    }
}
void dfs2(int a) {
    v2[a]=true;
    for (int x:sz[a]) {
        if (!v2[x]) {
            //f[x]=a;
            l=a, ki=x, ut=x;
            dfs3(x);
            add(a, ut, x);
        }
    }
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin >> n;
    for (int i=1; i<n; i++) {
        int a, b; cin >> a >> b;
        sz[a].push_back(b), sz[b].push_back(a);
    }
    h=(n+1)/2;
    dfs1(1);
    for (int i=1; i<=n; i++) {
        if (cen[i]) {
            dfs2(i);
        }
    }

    int si=sol.size();
    cout << si << "\n";
    for(int i=0; i<si; i++) {
        cout << sol[i].first << " " << sol[i].second.first << " " << sol[i].second.second << "\n";
    }

    return 0;
}

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

struct trio{
	int f1, f2 ,f3;
	trio(int n1 = 0, int n2 = 0, int  n3 = 0) {
		f1 = n1, f2 = n2, f3 = n3;
	}
};

const int maxn = 2e5 + 20;

short int visited[maxn];
int n, cent, th[maxn], lasti;
vector <trio> ans;
vector <int> graph[maxn];

void cnFinder(int i) {
	visited[i] = 1;
	bool c = 1;
	for (int x : graph[i])
		if (!visited[x]) {
			cnFinder(x);
			th[i] += th[x];
			if (th[x] > n / 2)
				c = 0;
		}
	th[i]++;
	if (n  - th[i] > n / 2)
		c = 0;
	if (c)
		visited[i] = 2, cent = i;
}
void change(int i, int par, int j, int cn) {
	if (visited[i] == 2) {
		for (int x : graph[i])
			if (x != par) {
				lasti = x;
				change (x, i, x, i);
			}
	}
	else{
		for (int x : graph[i])
			if (x != par)
				change(x, i, j, cn);
		if (i != j) {
			ans.push_back(trio(cn, lasti, i));
			lasti = i;
			ans.push_back(trio(i, par, j));
		}
		else
			ans.push_back(trio(cn, lasti, j));
	}
}
int main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 0, a, b; i < n - 1; i++){
		cin >> a >> b;
		graph[a].push_back(b);
		graph[b].push_back(a);
	}
	cnFinder(1);
	change(cent, 0, 0, 0);
	cout << ans.size() << endl;
	for (trio x : ans)
		cout << x.f1 << " " << x.f2 << " " << x.f3 << endl;
}

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctime>
#include <cassert>
#include <unordered_map>
#include <fstream>
#include <random>
#include <cstring>
#include <complex>
#include <bitset>

#define all(a) (a).begin(), (a).end()
#define sz(a) (int)(a).size()
#define pb push_back

using namespace std;

mt19937 rr(random_device{}());

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double ld;

const int MAXN = 3e5;

vector<int> g[MAXN];
int p[MAXN];
int w[MAXN];
int used[MAXN];

int deg[MAXN];

struct Request {
    int x, y, z;
};

vector<Request> req;

void request(int x, int y, int z) {
    req.push_back({x, y, z});
}

int dfs1(int v, int par = -1) {
    w[v] = 1;
    p[v] = par;
    for (int u : g[v]) {
        if (u == par)
            continue;
        w[v] += dfs1(u, v);
    }
    return w[v];
}

int last;

vector<int> leaves;
vector<int> path;

void getLeaves(int v, int par = -1) {
    if (deg[v] == 1) {
        leaves.push_back(v);
    }

    for (int u : g[v]) {
        if (u == par || used[u])
            continue;
        getLeaves(u, v);
    }
}

void getPath(int v, int c) {
    path.push_back(v);

    int u = leaves.back();
    leaves.pop_back();
    used[u] = true;

    int t = -1;

    for (int w : g[u]) {
        --deg[w];
        if (deg[w] == 1 && !used[w])
            leaves.push_back(w);
        if (!used[w])
            t = w;
    }

    request(v, c, u);
    if (t != -1) {
        getPath(u, t);
    } else {
        path.push_back(u);
    }
}

int main() {
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n;
    for (int i = 0; i < n - 1; ++i) {
        int u, v;
        cin >> u >> v;
        --u; --v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    dfs1(0);
    vector<int> cen;

    for (int v = 0; v < n; ++v) {
        bool f = true;
        if (2 * (n - w[v]) > n)
            f = false;
        for (int u : g[v]) {
            if (2 * w[u] > n && u != p[v])
                f = false;
        }
        if (f)
            cen.push_back(v);
    }

    for (int v : cen) {
        used[v] = 1;
    }

    for (int i = 0; i < n; ++i) {
        for (int u : g[i]) {
            if (!used[u])
                ++deg[i];
        }
    }

    for (int v : cen) {
        for (int u : g[v]) {
            if (deg[u] == 0 || used[u])
                continue;
            leaves.clear();
            getLeaves(u);

            path.clear();
            getPath(v, u);

            int k = sz(path);
            for (int i = k - 4; i >= 0; --i)
                request(path[i], path[i + 1], path[k - 2]);
        }
    }

    cout << sz(req) << "\n";
    for (int i = 0; i < sz(req); ++i) {
        cout << req[i].x + 1 << " " << req[i].y + 1 << " " << req[i].z + 1 << "\n";
    }

    return 0;
}

#include <bits/stdc++.h>

#define fir first
#define sec second
using namespace std;
typedef long long LL;
typedef unsigned long long u64;

template <typename T> inline bool cmin(T & a, const T & b) { return a > b ? a = b, 1 : 0;}
template <typename T> inline bool cmax(T & a, const T & b) { return a < b ? a = b, 1 : 0;}
int read() {
	int x = 0, f = 1;char ch;
	for(ch = getchar(); !isdigit(ch); ch = getchar())
		if(ch == '-') f = -1;
	for(; isdigit(ch); x = x * 10 + ch - '0', ch = getchar());
	return x * f;
}

const int MaxN = 201234;

int n, siz[MaxN];
vector<int> e[MaxN];
vector<pair<int, int>> v;
vector<pair<int, pair<int, int>>> ans;

void Siz(int x, int fa = 0) {
	siz[x] = 1;
	for(auto y : e[x])
		if(y != fa)
			Siz(y, x), siz[x] += siz[y];
}

int par;
int Cent(int x, int fa = 0) {
	for(auto y : e[x])
		if(y != fa)
			if(siz[y] > n / 2)
				return Cent(y, x);
	par = fa; return x;
}

void dfs(int x, int fa = 0) {
	for(auto y : e[x])
		if(y != fa)
			dfs(y, x);
	v.push_back(make_pair(x, fa));
}

void Ans(int x, int fa = 0) {
	v.clear();
	dfs(x, fa);
	v.pop_back();
	int t = x;
	for(auto y : v) {
		ans.push_back(make_pair(fa, make_pair(t, y.fir)));
		ans.push_back(make_pair(y.fir, make_pair(y.sec, x)));
		t = y.fir;
	}
	ans.push_back(make_pair(fa, make_pair(t, x)));
}

int main() {
	int i;
	n = read();
	for(i = 1; i < n; i++) {
		int u = read(), v = read();
		e[u].push_back(v);
		e[v].push_back(u);
	}

	Siz(1);

	int cent1 = Cent(1), cent2 = 0;

    for(auto y : e[cent1])
		if(par != y && 2 * siz[y] == n)
			cent2 = y;
    for(auto y : e[cent1])
		if(y != cent2)
			Ans(y, cent1);
    for(auto y : e[cent2])
		if(y != cent1)
			Ans(y, cent2);

	printf("%d\n", ans.size());
	for(auto x : ans)
		printf("%d %d %d\n", x.fir, x.sec.fir, x.sec.sec);

	return 0;
}

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<cassert>
#define PB push_back
#define MP make_pair
#define sz(v) (in((v).size()))
#define forn(i,n) for(in i=0;i<(n);++i)
#define forv(i,v) forn(i,sz(v))
#define fors(i,s) for(auto i=(s).begin();i!=(s).end();++i)
#define all(v) (v).begin(),(v).end()
using namespace std;
typedef int in;
typedef vector<in> VI;
typedef vector<VI> VVI;
VVI egs;
VI blw;
VI lrgc;
in gentot(const in& u, const in& pr){
  blw[u]=1;
  lrgc[u]=0;
  in tup;
  in ts=sz(egs[u]);
  forn(i,ts){
    tup=egs[u][i];
    if(tup==pr)
      continue;
    blw[u]+=gentot(tup,u);
    lrgc[u]=max(lrgc[u],blw[tup]);
  }
  return blw[u];
}
in n;
VI solx,soly,solyy;
in curpt;
void findbot(in cur, in pr, in cent, in gol){
  bool hasg=0;
  if(cur==gol)
    hasg=1;
  in v;
  forv(i,egs[cur]){
    v=egs[cur][i];
    if(v==gol){
      hasg=1;
    }
    if(v!=pr){
      findbot(v,cur,cent,gol);
    }
  }
  if(!hasg){
    solx.PB(cent);
    soly.PB(curpt);
    solyy.PB(cur);
    curpt=cur;
    solx.PB(cur);
    soly.PB(pr);
    solyy.PB(gol);
  }
}
void gen(in bpt){
  if(sz(lrgc)==0){
    lrgc.resize(sz(egs));
    blw.resize(sz(egs));
  }
  gentot(bpt,bpt);
  in msz=blw[bpt];
  VI c;
  forn(i,n){
    if(blw[i]*2>=msz && lrgc[i]*2<=msz){
      c.PB(i);
    }
  }
  assert(sz(c)>=1 && sz(c)<=2);
  in u,v;
  forv(i,c){
    u=c[i];
    forv(j,egs[u]){
      v=egs[u][j];
      if(v==c[0] || (sz(c)==2 && v==c[1]))
	continue;
      curpt=v;
      findbot(v,u,u,v);
      soly.PB(curpt);
      solx.PB(u);
      solyy.PB(v);
    }
  }
}

int main(){
  ios::sync_with_stdio(0);
  cin.tie(0);
  cin>>n;
  egs.resize(n);
  in ta,tb;
  forn(z,n-1){
    cin>>ta>>tb;
    --ta;
    --tb;
    egs[ta].PB(tb);
    egs[tb].PB(ta);
  }
  gen(0);
  cout<<sz(solx)<<"\n";
  forv(i,solx){
    cout<<solx[i]+1<<" "<<soly[i]+1<<" "<<solyy[i]+1<<"\n";
  }
  return 0;
}

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
#define print(v,r) f(i,0,r) cout<<v[i]<<" "; cout<<endl;
#define Get(x,y) scanf("%I64d%I64d",&x,&y);
#define is_bit(x,y) (x%(1<<(y+1))>=(1<<y))
#define eror(x) cout<<#x<<'='<<(x)<<endl;
#define f_(i,a,b) for(int i=a;i>=b;i--)
#define Gett(x,y) scanf("%d%d",&x,&y);
#define f(i,a,b) for(int i=a;i<b;i++)
#define get(x) scanf("%I64d",&x);
#define gett(x) scanf("%d",&x);
#define maxm(a,b) a=max(a,b);
#define minm(a,b) a=min(a,b);
#define Add(x,y) x=(x+y)%mod
#define lst(x) x[x.size()-1]
#define sz(x) int(x.size())
#define mp make_pair
#define ll long long
#define pb push_back
#define S second
#define F first

const int N=5e5+99;

int n,u,v,t,last,sub[N],par[N],deg[N];
queue<int> q;
vector<int> cent,g[N];
vector<pair<int,pair<int,int> > > ans;

void read(){
	cin>>n;
	f(i,1,n){
		Gett(u,v);
		g[u].pb(v);
		g[v].pb(u);
		deg[u]++;
		deg[v]++;
	}
}
void dfs(int x,int par){
	bool is_cent=1;
	sub[x]=1;
	f(i,0,g[x].size())
		if(g[x][i]!=par){
			dfs(g[x][i],x);
			sub[x]+=sub[g[x][i]];
			is_cent&=(sub[g[x][i]]<=n/2);
		}
	is_cent&=(n-sub[x]<=n/2);
	if(is_cent)
		cent.pb(x);
}
void dfs1(int x,int rt){
	if(x!=rt && par[x]!=rt && g[x].size()==1) q.push(x);
	f(i,0,g[x].size())
		if(g[x][i]!=par[x]){
			par[g[x][i]]=x;
			dfs1(g[x][i],rt);
		}
}
void change(int u,int rt,int cent){
	ans.pb(mp(cent,mp(last,u)));
	ans.pb(mp(u,mp(par[u],rt)));
	deg[par[u]]--;
	last=u;
	if(par[par[u]]!=rt && deg[par[u]]==1)
		q.push(par[u]);
}
void solve(int rt,int cent){
	par[rt]=cent;
	dfs1(rt,rt);
	last=rt;
	while(q.size()){
		int u=q.front();
		q.pop();
		change(u,rt,cent);
	}
	ans.pb(mp(cent,mp(last,rt)));
}
void do_it(){
	f(k,0,sz(cent)){
		u=cent[k];
		f(i,0,g[u].size())
			if(g[u][i]!=cent[0] && g[u][i]!=lst(cent))
				solve(g[u][i],cent[k]);
	}
	cout<<sz(ans)<<'\n';
	f(i,0,sz(ans))
		cout<<ans[i].F<<" "<<ans[i].S.F<<" "<<ans[i].S.S<<'\n';
}
void find_centroids(){
	dfs(1,0);
}

int main(){
	read();
	find_centroids();
	do_it();
}

#define _CRT_SECURE_NO_DEPRECATE
#pragma comment(linker, "/STACK:167772160000")
#include <iostream>
#include <fstream>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <stdlib.h>
#include <string>
#include <list>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
#include <iomanip>
#include <queue>
#include <deque>
#include <set>
#include <stack>
#include <sstream>
#include <assert.h>
#include <functional>
#include <climits>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
//typedef uint64_t ull;
//typedef std::pair<long double,long double> pdd;
#define for8(i) for( i = 1; i<=8; i++)
#define fori(N)          for(int i = 0; i<(N); i++)
#define forj(N)         for(int j = 0; j<(N); j++)
#define fork(N)         for(int k = 0; k<(N); k++)
#define forl(N)         for(int l = 0; l<(N); l++)
#define ford(N)         for(int d = 0; d<(N); d++)
#define fori1(N)          for(int i = 1; i<=(N); i++)
#define forj1(N)         for(int j = 1; j<=(N); j++)
#define fork1(N)         for(int k = 1; k<=(N); k++)
#define ford1(N)         for(int d = 1; d<=(N); d++)
#define forl1(N)         for(int l = 1; l<=(N); l++)
#define PI (2*asin(1))
#define print(n) printf("%d ", (n))
#define printll(n) printf("%I64d ", (n))
#define printline() printf("\n")
#define read(n) scanf("%d", &n);
#define read2(n, m) scanf("%d%d", &n, &m);
#define readll(n) scanf("%I64d", &n);
#define mp make_pair

vector<pii>edges[210000];
bool isCenter[210000];
int n;
set<int>sedges[210000];
int dfs1(int a, int par) {
	isCenter[a] = true;
	int ret = 1;
	fori(edges[a].size()) {
		if (edges[a][i].first == par)continue;
		edges[a][i].second = dfs1(edges[a][i].first, a);
		ret += edges[a][i].second;

	}
	fori(edges[a].size()) {
		if (edges[a][i].first == par)
			edges[a][i].second = n - ret;
		if (edges[a][i].second > n / 2)
			isCenter[a] = false;
	}
	return ret;
}
vector<pair< int, pii> >answer;
vector<int>currentEdges;
void dfs2(int a, int par) {
	currentEdges.push_back(a);
	fori(edges[a].size()) {
		if (edges[a][i].first == par)continue;
		dfs2(edges[a][i].first, a);
	}
}
void makeGood(int from, int cur) {
	int curPos = cur;
	currentEdges.clear();
	dfs2(cur, from);
	stack<int>leaves;
	fori(currentEdges.size()) {
		int x = currentEdges[i];
		if (sedges[x].size() == 1)
			leaves.push(x);
}
	while (!leaves.empty()) {
		int x = leaves.top();
		leaves.pop();
		if (x == cur)continue;
		if (*(sedges[x].begin()) == cur)continue;
		if(x!=curPos)
		answer.push_back(mp(from, pii(curPos, x)));
		curPos = x;
		int y = *(sedges[x].begin());
		answer.push_back(mp(x, pii(y, cur)));
		sedges[y].erase(x);
		if (sedges[y].size() == 1)leaves.push(y);
	}
	if(curPos!=cur)
		answer.push_back(mp(from, pii(curPos, cur)));
}
int main()
{
#if defined(_DEBUG)
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> n;
	fori(n - 1) {
		int a, b; cin >> a >> b;
		sedges[a].insert(b);
		sedges[b].insert(a);
		edges[a].push_back(pii(b, 0));
		edges[b].push_back(pii(a, 0));
	}
	dfs1(1, 1);
	fori1(n) {
		if (!isCenter[i])continue;
		forj(edges[i].size()) {
			int x = edges[i][j].first;
			if (isCenter[x])continue;
			makeGood(i, x);

		}
	}
	cout << answer.size() << "\n";
	for(auto x : answer) {
		cout << x.first << " " << x.second.first << " " << x.second.second << "\n";
	}
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define f first
typedef long long ll;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int oo = 1000000001;
const int N = 200011;

int n, sz[N], st[N], ed[N], cnt = 1, vis[N], bk[N];
vector<int> g[N], ch[N], cen;
pii E[N];
bool blk[N];
set<int> all;

void pre(int u, int p = -1) {
	sz[u] = 1;
	bk[cnt] = u;
	st[u] = cnt++;
	for (int i = 0; i < g[u].size(); ++i) {
		int v = g[u][i];
		if (v == p || blk[v])continue;
		pre(v, u);
		sz[u] += sz[v];
	}
	ed[u] = cnt - 1;
}
void findCen(int u, int p = -1) {
	int mx = -1;
	for (int i = 0; i < g[u].size(); ++i) {
		int v = g[u][i];
		if (v == p)continue;
		mx = max(mx, sz[v]);
		findCen(v, u);
	}
	mx = max(mx, n - sz[u]);
	if (mx * 2 <= n) {
		cen.push_back(u);
	}
}
vector< pii > order;
vector< pair<int, pii > > res;

void chain(int u) {
	vis[u] = 1;
	all.erase(st[u]);
	for (int i = 0; i < g[u].size(); ++i) {
		int v = g[u][i];
		if (vis[v] || blk[v])continue;
		set<int>::iterator it = --all.upper_bound(ed[v]);
		if (bk[*it] != v)
			res.push_back(make_pair(u, make_pair(v, bk[*it])));
		ch[u].push_back(bk[*it]);
		ch[bk[*it]].push_back(u);
		chain(bk[*it]);
		if (!blk[u])
			break;
	}
}

void get(int u , int p = -1) {
	order.push_back(make_pair(u, 0));
	for (int i = 0; i < ch[u].size(); ++i) {
		if (ch[u][i] == p)continue;
		get(ch[u][i], u);
	}
}
void goFind(int root) {
	chain(root);
	for (int i = 0; i < ch[root].size(); ++i) {
		order.clear();
		if(blk[ch[root][i]])continue;
		get(ch[root][i], root);
		int last = order.back().f;
		for (int j = (int)order.size() - 3; j >= 0 ; j--) {
			res.push_back(make_pair(order[j].f, make_pair(order[j + 1].f, last)));
		}
		res.push_back(make_pair(root, make_pair(order[0].f, last)));

	}
}

int main() {
	//freopen("input.txt", "r", stdin);
	scanf("%d", &n);
	for (int i = 0; i < n - 1; ++i) {
		scanf("%d%d", &E[i].first, &E[i].second);
		g[E[i].first].push_back(E[i].second);
		g[E[i].second].push_back(E[i].first);
	}
	pre(1);
	findCen(1);
	for (int i = 0; i < cen.size(); ++i) {
		vis[cen[i]] = 1;
		blk[cen[i]] = 1;
	}
	for (int i = 0; i < cen.size(); ++i) {
		for (int j = 1 ; j <= n ; j++)all.insert(j);
		cnt = 1;
		pre(cen[i]);
		goFind(cen[i]);
	}
	printf("%d\n", (int)res.size() );
	for (int i = 0; i < res.size(); ++i) {
		printf("%d %d %d\n", res[i].first, res[i].second.first, res[i].second.second);
	}
	return 0;
}

#include<cstdio>
#include<vector>
using namespace std;
int cnt[200001], n, par;
vector<int> adj[200001];
vector<pair<int, int> > v;
void count(int h, int p) {
    cnt[h]++;
    for (auto it : adj[h]) if (it^p) {
        count(it, h);
        cnt[h] += cnt[it];
    }
}
int ct(int h, int p) {
    for (auto it : adj[h]) if (it^p) {
        if (cnt[it] > n / 2) return ct(it, h);
    }
    par = p;
    return h;
}
vector<pair<int, pair<int, int> > > res;
void dfs(int h, int p) {
    for (auto it : adj[h]) if (it^p) {
        dfs(it, h);
    }
    v.push_back({ h,p });
}
void f(int h, int p) {
    v.clear();
    dfs(h, p);
    v.pop_back();
    int t = h;
    for (auto it : v) {
        res.push_back({ p,{t,it.first} });
        res.push_back({ it.first,{it.second,h} });
        t = it.first;
    }
    res.push_back({ p,{t,h} });
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    count(1, 0);
    int cen = ct(1, 0), cen2 = 0;
    for (auto it : adj[cen]) if (par^it && 2*cnt[it] == n) cen2 = it;
    for (auto it : adj[cen]) if (it^cen2) f(it, cen);
    for (auto it : adj[cen2]) if (it^cen) f(it, cen2);
    printf("%d\n", res.size());
    for (auto it : res) printf("%d %d %d\n", it.first, it.second.first, it.second.second);
    return 0;
}

#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define mp make_pair
#define PI ( acos(-1.0) )
#define IN freopen("C.in","r",stdin)
#define OUT freopen("output.txt","w",stdout)
#define DBG printf("Hi\n")
#define i64 long long int
#define ui64 unsigned long long int
#define eps (1e-10)
#define xx first
#define yy second
#define ln 17
#define off 2

#define FASTIO ios_base::sync_with_stdio(false); cin.tie(NULL)

using namespace __gnu_pbds;
using namespace std ;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
typedef tree< i64, null_type, less<i64>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
typedef pair<int,int> pii;

#define log 20
#define mod 998244353LL
#define maxn 200005
#define INF 1000000000

int sub[maxn] ;
vector <int> g[maxn] ;

void dfs0(int u, int par)
{
    sub[u] = 1 ;
    for(int i=0 ; i<g[u].size() ; i++)
    {
        int v = g[u][i] ;
        if( v==par ) continue ;
        dfs0(v,u) ;
        sub[u] += sub[v] ;
    }
}
int findCentroid(int u, int par , int n)
{
    for(int v:g[u])
    {
        if(v==par) continue ;
        if( sub[v] > n/2 ) return findCentroid(v,u,n) ;
    }
    return u ;
}

set < pair<int,int> > edge ;

void Remove(int u, int v)
{
    edge.erase( edge.find( mp(u,v) ) ) ;
    edge.erase( edge.find( mp(v,u) ) ) ;
}
void Add(int u, int v)
{
    edge.insert( mp(u,v) ) ; edge.insert( mp(v,u) ) ;
}

vector < pair< pair<int,int> , int > > ans ;

void MakeOperation( int u , int v , int x )
{
    Remove(u,v) ;
    Add(u,x) ;
    ans.pb( mp( mp(u,v), x ) ) ;
}

pair<int,int> dfs1(int u, int par)
{
    vector < pair<int,int> > vp ;
    for(int i=0 ; i<g[u].size() ; i++)
    {
        int v = g[u][i] ;
        if( v==par ) continue ;
        vp.pb( dfs1(v,u) ) ;
    }
    if(vp.size()==0) return mp(u,u) ;

    if( vp.size() == 1 ) return mp( u , vp[0].yy ) ;

    int curPar = par ;
    for(int i=0 ; i+1 < vp.size() ; i++)
    {
        MakeOperation( curPar , u , vp[i].yy ) ;
        curPar = vp[i].xx ;
    }
    return mp( vp[0].yy , vp.back().yy ) ;
}

int dfs2(int u ,int par)
{
    if( g[u].size()==1 ) return u ;

    int v = dfs2( (g[u][0]^g[u][1]^par) , u ) ;

    MakeOperation( par , u , v ) ;

    return v ;
}

int main()
{
    int n ;

    scanf("%d",&n) ;

    for(int i=1 ; i<n ; i++)
    {
        int u , v ;
        scanf("%d %d",&u,&v) ;
        g[u].pb(v) ; g[v].pb(u) ;
        edge.insert( mp(u,v) ) ; edge.insert( mp(v,u) ) ;
    }

    dfs0(1,0) ;

    int cent = findCentroid(1,0,n) ;

    dfs0(cent,0) ;

    for(int i=0 ; i<g[cent].size() ; i++)
    {
        if( sub[ g[cent][i] ]*2 == n  )
        {
            int u = g[ cent ][ i ] ;
            for(int j=0 ; j<g[u].size() ; j++) if( g[u][j] != cent ) dfs1(  g[u][j] , u) ;
        }
        else dfs1( g[cent][i] , cent ) ;
    }

    for(int i=1 ; i<=n ; i++) g[i].clear() ;

    for(auto e: edge)
    {
//        if( e.xx < e.yy ) printf("-- %d %d\n",e.xx,e.yy) ;
        g[ e.xx ].pb( e.yy ) ;
    }

//    for(int i=1; i<=n ; i++) printf("%d\n",g[i].size()) ;

    for(int i=0 ; i<g[cent].size() ; i++)
    {
        if( sub[ g[cent][i] ]*2 == n  )
        {
            int u = g[ cent ][ i ] ;
            for(int j=0 ; j<g[u].size() ; j++) if( g[u][j] != cent ) dfs2(  g[u][j] , u) ;
        }
        else dfs2( g[cent][i] , cent ) ;
    }

    for(auto e: edge)
    {
  //      if( e.xx < e.yy ) printf("-- %d %d\n",e.xx,e.yy) ;
    }

    printf("%d\n",ans.size()) ;
    for(auto a: ans) printf("%d %d %d\n" , a.xx.xx , a.xx.yy , a.yy ) ;

    return 0 ;
}
/*
13
1 2
2 4
2 5
4 8
8 12
8 13
1 3
3 6
3 7
6 10
6 11
7 9
*/

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstdio>
#include <cmath>
#include <map>
#include <set>
#include <utility>
#include <stack>
#include <cstring>
#include <bitset>
#include <deque>
#include <cassert>
#include <string>
#include <list>
#include <cstdlib>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 200000 + 100;
typedef long long ll;
typedef long double ld;
vector<int> st;
int pv[maxn], sz[maxn];
vector<int> g[maxn];
vector<int> jobs[maxn];
int depth[maxn];
bool flag;
void dfs(int v, int pr)
{
	st.push_back(v);
	pv[v] = pr;
	sz[v] = 1;
	for (int u : g[v])
	{
		if (u == pr)
			continue;
		depth[u] = depth[v] + 1;
		dfs(u, v);
		sz[v] += sz[u];
	}
	if (flag && depth[v] >= 3)
	{
		jobs[st[1]].push_back(v);
	}
	st.pop_back();
}
int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n - 1; i++)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		x--;
		y--;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	flag = false;
	dfs(0, -1);
	vector<int> roots;
	for (int i = 0; i < n; i++)
	{
		int outer = n - sz[i];
		if (outer > n / 2)
		{
			continue;
		}
		bool ok = true;
		for (int j : g[i])
		{
			if (j == pv[i])
			{
				continue;
			}
			if (sz[j] > n / 2)
			{
				ok = false;
				break;
			}
		}
		if (ok)
		{
			roots.push_back(i);
		}
	}
	assert(!roots.empty());
	flag = true;
	if (roots.size() == 1)
	{
		depth[roots[0]] = 0;
		dfs(roots[0], -1);
	}
	else
	{
		depth[roots[0]] = depth[roots[1]] = 0;
		dfs(roots[0], roots[1]);
		dfs(roots[1], roots[0]);
	}
	vector<pair<int, pair<int, int> > > res;
	for (int i = 0; i < n; i++)
	{
		if (jobs[i].empty())
		{
			continue;
		}
		int at = i;
		for (int v : jobs[i])
		{
			res.emplace_back(pv[i], make_pair(at, v));
			res.emplace_back(v, make_pair(pv[v], i));
			at = v;
		}
		res.emplace_back(pv[i], make_pair(at, i));
	}
	int cnt = res.size();
	printf("%d\n", cnt);
	for (int i = 0; i < cnt; i++)
	{
		printf("%d %d %d\n", res[i].first + 1, res[i].second.first + 1, res[i].second.second + 1);
	}
//	system("pause");
	return 0;
}

// :(
#ifndef LOCAL
#define NDEBUG 1
#endif
#include<bits/stdc++.h>

std::vector<std::vector<int>> add;

int number;
int throwCentroid(int const node, int par){
	int maxChild=-1;
	int subsize=1;
	for(auto it: add[node]) if(it!=par){
		//add[it].erase(std::find(begin(add[it]), end(add[it]), node));
		int childSize=throwCentroid(it, node);
		maxChild=std::max(maxChild, childSize);
		subsize+=childSize;
	}
	if(std::max(number-subsize, maxChild)*2<=number){
		if(subsize*2==number)
			throw std::pair{node, par};
		else
			throw std::pair{node, -1};
	}
	return subsize;
}
auto findCentroid(){
	try{
		throwCentroid(0, -1);
	}catch(std::pair<int, int> centroid){
		return centroid;
	}
	assert(false); __builtin_unreachable();
}

#if LOCAL
#define local(...) __VA_ARGS__
#else
#define local(...)
#endif

local(std::vector<std::vector<int>> add1;)

std::vector<std::array<int, 3>> operations;
void operation(int a, int b, int c){
	operations.push_back({a, b, c});
#if LOCAL
	add1[a].erase(std::find(begin(add1[a]), end(add1[a]), b));
	add1[b].erase(std::find(begin(add1[b]), end(add1[b]), a));
	add1[a].push_back(c);
	add1[c].push_back(a);
#endif
}

struct List{
	std::vector<int> data;
	local(std::vector<int> someAdjacent;)

	List(){}
	List(int number): data(number)
					  local(
							  , someAdjacent(number, -1)
							  )
	{
		for(int i=0; i<number; ++i){
			assert(adjacent(i, -1));
			assert(step(-1, i)==-1);
		}
	}

	int step(int previous, int cur) const{
		assert(adjacent(cur, previous));
		assert(adjacent(cur, data[cur]^previous));
		return data[cur]^previous;
	}

	local(
	bool adjacent(int node, int other) const{
		return other==someAdjacent[node] or other==(data[node]^someAdjacent[node]);
	}
	)

	void link(int first, int sec){
		assert(adjacent(first, -1));
		assert(adjacent(sec, -1));
		local(someAdjacent[first]=sec; someAdjacent[sec]=first;)
		data[first]^=(-1)^sec;
		data[sec]^=(-1)^first;
		assert(adjacent(first, sec));
		assert(adjacent(sec, first));
	}
};

List list;

std::pair<int, int> work2(int const par, int const node){
	assert(list.adjacent(node, -1));

	assert(par>=0);
	assert(std::find(begin(add[node]), end(add[node]), par)!=add[node].end());
	assert(std::find(begin(add1[node]), end(add1[node]), par)!=add1[node].end());
	if(add[node].size()==1){
		assert(add1[node].size()==1);
		return {node, node};
	}

	int resultX=-1;
	auto par1=par;

	for(auto const child: add[node]) if(child!=par){
		auto const [x, y]=work2(node, child);
		operation(par1, node, y);
		if(resultX<0)
			resultX=y;
		else
			list.link(par1, y);
		par1=x;
	}
	list.link(par1, node);
	assert(list.adjacent(resultX, -1));
	assert(list.adjacent(node, -1));
	assert(([&]{
		int tmp=node, last=-1;
		while(tmp!=resultX) {
			std::tie(last, tmp)=std::pair(tmp, list.step(last, tmp));
			assert(tmp>=0);
		}
		return true;
	}()));

	assert(add1[node].size()==1);
	return {resultX, node};
}

void work(int node, int par){
	for(auto child: add[node]) if(child!=par){
		auto [x, y]=work2(node, child);
		child=-1;
		assert(list.adjacent(y, -1));
		assert(list.adjacent(x, -1));

		if(x!=y){
			int last=y, z=y;
			y=list.step(-1, y);
			while(y!=x){
				auto const a=list.step(last, y);
				operation(a, y, z);
				last=y; y=a;
			}
			operation(node, y, z);
		}

	}
}

int main(){
	std::ios::sync_with_stdio(0);std::cin.tie(0);
	std::cin>>number;
	add.clear();
	add.resize(number);
	for(int _=0; _<number-1; ++_){
		int first, sec; std::cin>>first>>sec;
		--first;--sec;
		add[first].push_back(sec);
		add[sec].push_back(first);
	}

	local(add1=add;)

	auto centroid=findCentroid();
	operations.clear();
	list=List(number);
	if(centroid.second<0){
		work(centroid.first, -1);
	}else{
		work(centroid.first, centroid.second);
		work(centroid.second, centroid.first);
	}

	std::cout<<operations.size()<<'\n';
	for(auto it: operations){
		for(auto it: it) std::cout<<it+1<<' ';
		std::cout<<'\n';
	}

}

#include<bits/stdc++.h>
using namespace std;
vector<int> v[200010],c[200010],rt;
int n,siz[200010],fa[200010],dep[200010];
vector<pair<int,pair<int,int> > > ans;
void dfs1(int np,int fath)
{
	bool isrt=1;
	siz[np]=1;
	for(int x:v[np])
	{
		if(x==fath)continue;
		dfs1(x,np);
		siz[np]+=siz[x];
		if(siz[x]>(n>>1))isrt=0;
	}
	if(n-siz[np]>(n>>1))isrt=0;
	if(isrt)rt.push_back(np);
}
int stk[200010],top;
void dfs2(int np,int fath)
{
	fa[np]=fath;
	stk[top++]=np;
	if(dep[np]>=3)
		c[stk[1]].push_back(np);
	for(int x:v[np])
	{
		if(x==fath)continue;
		dep[x]=dep[np]+1;
		dfs2(x,np);
	}
	top--;
}
int main()
{
	scanf("%d",&n);
	for(int i=1,ti,tj;i<n;i++)
	{
		scanf("%d%d",&ti,&tj);
		v[ti].push_back(tj);
		v[tj].push_back(ti);
	}
	dfs1(1,0);
	if(rt.size()==1)
		dfs2(rt[0],0);
	else
		dfs2(rt[0],rt[1]),dfs2(rt[1],rt[0]);
	for(int i=1;i<=n;i++)if(c[i].size())
	{
		int cur=i;
		for(int p:c[i])
		{
			ans.push_back(make_pair(fa[i],make_pair(cur,p))),ans.push_back(make_pair(p,make_pair(fa[p],i)));
			cur=p;
		}
		ans.push_back(make_pair(fa[i],make_pair(cur,i)));
	}
	printf("%d\n",ans.size());
	for(int i=0;i<ans.size();i++)
		printf("%d %d %d\n",ans[i].first,ans[i].second.first,ans[i].second.second);
	return 0;
}

// In the name of God

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define Size(x) ((int)(x).size())
typedef pair<int , int>pii;
const int INF = 1e9 + 10 , MN = 2e5 + 10;

vector<int>adj[MN];
vector<pair<pii , int> >ans;

int n;
bool mk[MN];
int par[MN] , q[MN] , L , R , sz[MN];

int prep(int s,int pr){
	sz[s] = 1;
	for(auto v:adj[s]) if(v ^ pr){
		par[v] = s;
		sz[s] += prep(v , s);
	}
	return sz[s];
}

void go(int cen,int s){
	mk[cen] = true;
	L = R = 0;
	q[R++] = s;
	mk[s] = true;
	par[s] = cen;
	while(L < R){
		int v = q[L++];
		for(auto u:adj[v]) if(!mk[u]){
			q[R++] = u;
			mk[u] = true;
			par[u] = v;
		}
	}
	pii lst(cen , s);
	vector<int>vec;
	vec.pb(cen);
	for(int i=R-1;~i;--i){
		int leaf = q[i];
		ans.pb({lst , leaf});
		lst = {leaf , par[leaf]};
		vec.pb(leaf);
	}
	for(int i=Size(vec)-2;~i;--i)
		ans.pb({{vec[i] , vec[i+1]} , vec.back()});

}

int main(){
	ios_base :: sync_with_stdio(false) , cin.tie(0) , cout.tie(0);
	cin >> n;
	for(int i=1;i<n;++i){
		int a,b;cin>>a>>b;--a,--b;
		adj[a].pb(b) , adj[b].pb(a);
	}
	prep(0 , -1);
	int mn = INF;
	pii my(-1 , -1);
	for(int i=0;i<n;++i){
		int Mx = n - sz[i];
		for(auto v:adj[i]) if(v != par[i])
			Mx = max(Mx , sz[v]);
		if(Mx < mn){
			mn = Mx;
			my = {i , -1};
		}else if(Mx == mn){
			if(~my.first) my.second = i;
			else my.first = i;
		}
	}
	if(~my.second){
		for(auto v:adj[my.first]) if(v != my.second)
			go(my.first , v);
		for(auto v:adj[my.second]) if(v != my.first)
			go(my.second , v);
	}else{
		for(auto v:adj[my.first])
			go(my.first , v);
	}
	cout << Size(ans) << '\n';
	for(auto x:ans)
		cout << x.first.first+1 << ' ' << x.first.second+1 << ' ' << x.second+1 << '\n';
	return 0;
}

// In the name of God

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define Size(x) ((int)(x).size())
typedef long long ll;
typedef long double ld;
typedef pair<int , int>pii;
const int INF = 1e9 + 10 , MN = 2e5 + 10;

vector<int>adj[MN];
vector<pair<pii , int> >ans;

int n;
bool mk[MN];
int par[MN] , q[MN] , L , R , sz[MN];

int prep(int s,int pr){
	sz[s] = 1;
	for(auto v:adj[s]) if(v ^ pr){
		par[v] = s;
		sz[s] += prep(v , s);
	}
	return sz[s];
}

void go(int cen,int s){
	mk[cen] = true;
	L = R = 0;
	q[R++] = s;
	mk[s] = true;
	par[s] = cen;
	while(L < R){
		int v = q[L++];
		for(auto u:adj[v]) if(!mk[u]){
			q[R++] = u;
			mk[u] = true;
			par[u] = v;
		}
	}
	pii lst(cen , s);
	vector<int>vec;
	vec.pb(cen);
	for(int i=R-1;~i;--i){
		int leaf = q[i];
		ans.pb({lst , leaf});
		lst = {leaf , par[leaf]};
		vec.pb(leaf);
	}
	for(int i=Size(vec)-2;~i;--i)
		ans.pb({{vec[i] , vec[i+1]} , vec.back()});

}

int main(){
	ios_base :: sync_with_stdio(false) , cin.tie(0) , cout.tie(0);
	cin >> n;
	for(int i=1;i<n;++i){
		int a,b;cin>>a>>b;--a,--b;
		adj[a].pb(b) , adj[b].pb(a);
	}
	prep(0 , -1);
	int mn = INF;
	pii my(-1 , -1);
	for(int i=0;i<n;++i){
		int Mx = n - sz[i];
		for(auto v:adj[i]) if(v != par[i])
			Mx = max(Mx , sz[v]);
		if(Mx < mn){
			mn = Mx;
			my = {i , -1};
		}else if(Mx == mn){
			if(~my.first) my.second = i;
			else my.first = i;
		}
	}
	if(~my.second){
		for(auto v:adj[my.first]) if(v != my.second)
			go(my.first , v);
		for(auto v:adj[my.second]) if(v != my.first)
			go(my.second , v);
	}else{
		for(auto v:adj[my.first])
			go(my.first , v);
	}
	cout << Size(ans) << '\n';
	for(auto x:ans)
		cout << x.first.first+1 << ' ' << x.first.second+1 << ' ' << x.second+1 << '\n';
	return 0;
}

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAXN = 2e5 + 10;

#define debug(...) fprintf(stderr, __VA_ARGS__)
#define fi first
#define se second
#define all(v) (v).begin(), (v).end()
#define fillchar(a, s) memset((a), (s), sizeof(a))

int N;
vector<int> adj[MAXN];

bool flag;
int par[MAXN], depth[MAXN], sub[MAXN];
vector<int> vvis;
vector<int> tasks[MAXN];

void dfs (int x, int p = 0, int d = 0) {
	vvis.push_back(x);
	par[x] = p;
	depth[x] = d;
	sub[x] = 1;

	for (int y : adj[x]) {
		if (y != p) {
			dfs(y, x, d + 1);
			sub[x] += sub[y];
		}
	}

	if (d >= 3 && flag) {
		tasks[vvis[1]].push_back(x);
	}
	vvis.pop_back();
}

int main() {
	scanf("%d", &N);
	for (int i = 1; i < N; i++) {
		int x, y;
		scanf("%d %d", &x, &y);
		adj[x].push_back(y);
		adj[y].push_back(x);
	}
	dfs(1);

	//ok let's determine centroids
	vector<int> roots;
	for (int i = 1; i <= N; i++) {
		bool iscent = true;
		for (int j : adj[i]) {
			int s = (j == par[i] ? N - sub[i] : sub[j]);
			if (s > N / 2) {
				iscent = false;
			}
		}

		if (iscent) {
			roots.push_back(i);
		}
	}

	flag = true;

	if (roots.size() == 1) {
		dfs(roots[0], 0);
	} else {
		dfs(roots[0], roots[1]);
		dfs(roots[1], roots[0]);
	}

	vector<pair<int, pii>> ans;
	for (int i = 1; i <= N; i++) {
		if (tasks[i].empty()) {
			continue;
		}

		int cur = i;
		for (int t : tasks[i]) {
			ans.emplace_back(par[i], pii(cur, t));
			ans.emplace_back(t, pii(par[t], i));
			cur = t;
		}
		ans.emplace_back(par[i], pii(cur, i));
	}

	printf("%lu\n", ans.size());
	for (auto p : ans) {
		printf("%d %d %d\n", p.fi, p.se.fi, p.se.se);
	}
}

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using db = double;
using vi = vector<int>;
#define pb push_back
#define fir first
#define sec second

const int maxn = 200006;

int n;
vector<int> e[maxn];
int s[maxn];
int A = -1, B = -1;

void build(int x, int p) {
	s[x] = 1;
	for (auto i : e[x])
		if (i != p) {
			build(i, x);
			s[x] += s[i];
		}
}

void Find(int x, int p) {
	//cout<<x<<' '<<p<<endl;
	for (auto i : e[x])
		if (i != p) {
			if (s[i] > n/2) {
				Find(i, x);
				return;
			}
			else if (s[i] == n/2 && n % 2 == 0) {
				A = x, B = i;
				return;
			}
		}
	A = x;
	return;
}

struct data {
	int x, y1, y2;
};

vector<data> ans;

int pre;
void dfs(int x, int p, int o, int t) {
	if (x != t) {
		ans.pb({o,pre,x});
		ans.pb({x,p,t});
		pre = x;
	}
	for (auto i : e[x])
		if (i != p)
			dfs(i, x, o, t);
}

int main() {
	scanf( "%d", &n );
	for (int i = 1; i < n; ++i) {
		int a, b;
		scanf( "%d%d", &a, &b );
		e[a].pb(b);
		e[b].pb(a);
	}
	build(1,0);
	Find(1,0);
	for (auto i : e[A])
		if (i != B) {
			pre = i;
			dfs(i,A,A,i);
			ans.pb({A,pre,i});
		}
	if (B != -1)
		for (auto i : e[B])
			if (i != A) {
				pre = i;
				dfs(i,B,B,i);
				ans.pb({B,pre,i});
			}
	cout<<ans.size()<<endl;
	for (auto i : ans) printf( "%d %d %d\n", i.x, i.y1, i.y2 );
}

// Copyright (C) 2017 __debug.

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; version 3

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; If not, see <http://www.gnu.org/licenses/>.

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

#define x first
#define y second
#define MP std::make_pair
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(), (x).end()
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#ifdef __linux__
#define getchar getchar_unlocked
#define putchar putchar_unlocked
#endif

using std::pair;
using std::vector;
using std::string;

typedef long long LL;
typedef pair<int, int> Pii;

const int oo = 0x3f3f3f3f;

template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, true : false; }
template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, true : false; }
string procStatus()
{
    std::ifstream t("/proc/self/status");
    return string(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>());
}
template<typename T> T read(T &x)
{
    int f = 1;
    char ch = getchar();
    for (; !isdigit(ch); ch = getchar())
        f = (ch == '-' ? -1 : 1);
    for (x = 0; isdigit(ch); ch = getchar())
        x = 10 * x + ch - '0';
    return x *= f;
}
template<typename T> void write(T x)
{
    if (x == 0) {
        putchar('0');
        return;
    }
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    static char s[20];
    int top = 0;
    for (; x; x /= 10)
        s[++top] = x % 10 + '0';
    while (top)
        putchar(s[top--]);
}
// EOT

const int MAXN = 2e5 + 5;

struct Edge {
    int v, next;
    Edge() { }
    Edge(int v_, int next_): v(v_), next(next_) { }
};

int N;
int tote, head[MAXN];
Edge edge[MAXN * 2 + 5];

inline void addEdge(int u, int v)
{
    edge[++tote] = Edge(v, head[u]);
    head[u] = tote;
}

void input()
{
    read(N);
    for (int i = 1; i < N; ++i) {
        int u, v;
        read(u); read(v);
        addEdge(u, v);
        addEdge(v, u);
    }
}

namespace Centroid
{

int size[MAXN];
int centroid;
int minmaxsubtree;

void dfs(int u, int f)
{
    int maxsonsize = 0;
    size[u] = 1;
    for (int i = head[u]; i; i = edge[i].next) {
        int v = edge[i].v;
        if (v == f)
            continue;
        dfs(v, u);
        size[u] += size[v];
        chkmax(maxsonsize, size[v]);
    }
    chkmax(maxsonsize, N - size[u]);
    if (chkmin(minmaxsubtree, maxsonsize))
        centroid = u;
}

int get()
{
    minmaxsubtree = +oo;
    dfs(1, 0);
    return centroid;
}

}

vector<std::tuple<int, int, int> > ans;
int S, T, L;

void dfs(int u, int fa)
{
    if (fa != S) {
        if (T != u) ans.push_back({S, T, u});
        if (fa != L) ans.push_back({u, fa, L});
        T = u;
    }
    for (int i = head[u]; i; i = edge[i].next) {
        int v = edge[i].v;
        if (v == fa)
            continue;
        dfs(v, u);
    }
}

void calc(int u, int fa)
{
    S = u;
    for (int i = head[u]; i; i = edge[i].next) {
        int v = edge[i].v;
        if (v == fa)
            continue;
        T = L = v;
        dfs(v, u);
        if (T != L) ans.push_back({S, T, L});
    }
}

void solve()
{
    int rt = Centroid::get();
    Centroid::dfs(rt, 0);
    for (int i = head[rt]; i; i = edge[i].next) {
        int v = edge[i].v;
        if (Centroid::size[v] * 2 == N) {
            calc(rt, v);
            calc(v, rt);
            goto OUTPUT;
        }
    }
    calc(rt, 0);

  OUTPUT:
    printf("%d\n", SZ(ans));
    for (auto &x : ans) {
        printf("%d %d %d\n", std::get<0>(x), std::get<1>(x), std::get<2>(x));
    }
}

int main()
{
#ifdef __DEBUG
    freopen("C.in", "r", stdin);
    freopen("C.out", "w", stdout);
#endif

    input();
    solve();

    return 0;
}

// 满地黄花堆积。憔悴损，如今有谁堪摘？
//     -- 李清照《声声慢·寻寻觅觅》

#include <bits/stdc++.h>
using namespace std;
vector<int> G[200200];
bool visited[200200] = {false};
int childCount[200200];
int parArr[200200];
int degree[200200];
int n;
int centroidMin;
int centroid1,centroid2;
bool doubleCentroid = false;
int findRoot(int x,int par) {
    // go !
    visited[x] = true;
    int ans = 1;
    for(int i : G[x]) {
        if(!visited[i]) {
            ans += findRoot(i,x);
        }
    }

    if(ans > n/2 && ans < centroidMin) {
        centroid1 = x;
        centroidMin = ans;
    }
    else if(n%2==0 && ans == n/2) {
        // double centroid
        doubleCentroid = true;
        centroid1 = x;
        centroid2 = par;
        centroidMin = n/2;
    }
    childCount[x] = ans;
    return ans;
}

queue<int> topoQ;
void buildTree(int now,int par) { // return leaf if exists
    parArr[now] = par;
    degree[now] = 1;
    for(auto i : G[now]) {
        if(i == par) continue;
        buildTree(i,now);
        degree[now]++;
    }
    if(degree[now] == 1) {
        topoQ.push(now);
    }
}

struct ansS {
    int x,y,yy;
};

vector<ansS> ansV;
void addAns(int x,int y,int yy) {
    if(y == yy) return;
    ansS a = {x,y,yy};
    ansV.push_back(a);
}

void solveSub(int root,int centroid) {
    // build bamboo
    while(!topoQ.empty()) topoQ.pop();
    buildTree(root,centroid);
    parArr[centroid] = root;
    degree[centroid] = 0;
    vector<int> bamboo;
    int last = centroid;
    int centroidTarg = topoQ.front();
    while(!topoQ.empty()) {
        int now = topoQ.front();
        topoQ.pop();
        addAns(last,parArr[last],now);
        last = now;
        bamboo.push_back(now);
        // reduce degree
        for(auto i : G[now]) {
            degree[i]--;
            if(degree[i] == 1) {
                topoQ.push(i);
            }
        }
    }
    /*printf("Solve %d,%d -> ",centroid,root);
    for(auto i : bamboo) printf("%d ",i);
    printf("\n");*/
    // build star graph
    if(bamboo.size() >= 2) {
        int starRoot = bamboo[bamboo.size()-2];
        for(int i = int(bamboo.size())-4;i >= 0;i--) {
            addAns(bamboo[i],bamboo[i+1],starRoot);
        }
        addAns(centroid,centroidTarg,starRoot);
    }

}

void solve(int centroid,int par) {
    // find each subchild
    for(auto i : G[centroid]) {
        if(i == par) continue;
        // solve subgraph
        solveSub(i,centroid);
    }
}
int main() {
    scanf("%d",&n);
    for(int i = 0;i < n-1;i++) {
        int a,b;
        scanf("%d %d",&a,&b);
        a--;
        b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    centroidMin = n;
    // build root
    findRoot(0,-1);
    // check double centroid
    if(doubleCentroid) {
        //printf("Double centroid %d %d\n",centroid1,centroid2);
        solve(centroid1,centroid2);
        solve(centroid2,centroid1);
    }
    else {
        //printf("Centroid %d\n",centroid1);
        solve(centroid1,-1);
    }

    printf("%d\n",ansV.size());
    for(auto i : ansV) {
        printf("%d %d %d\n",i.x+1,i.y+1,i.yy+1);
    }

}

#include <bits/stdc++.h>

using namespace std;

const int N = 1234567;

vector <int> st;
int pv[N], sz[N];
vector <int> g[N];
vector <int> jobs[N];
int depth[N];

bool flag;

void dfs(int v, int pr) {
  st.push_back(v);
  pv[v] = pr;
  sz[v] = 1;
  for (int u : g[v]) {
    if (u == pr) {
      continue;
    }
    depth[u] = depth[v] + 1;
    dfs(u, v);
    sz[v] += sz[u];
  }
  if (flag && depth[v] >= 3) {
    jobs[st[1]].push_back(v);
  }
  st.pop_back();
}

int main() {
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n - 1; i++) {
    int x, y;
    scanf("%d %d", &x, &y);
    x--; y--;
    g[x].push_back(y);
    g[y].push_back(x);
  }
  flag = false;
  dfs(0, -1);
  vector <int> roots;
  for (int i = 0; i < n; i++) {
    int outer = n - sz[i];
    if (outer > n / 2) {
      continue;
    }
    bool ok = true;
    for (int j : g[i]) {
      if (j == pv[i]) {
        continue;
      }
      if (sz[j] > n / 2) {
        ok = false;
        break;
      }
    }
    if (ok) {
      roots.push_back(i);
    }
  }
  assert(!roots.empty());
  flag = true;
  if ((int) roots.size() == 1) {
    depth[roots[0]] = 0;
    dfs(roots[0], -1);
  } else {
    depth[roots[0]] = depth[roots[1]] = 0;
    dfs(roots[0], roots[1]);
    dfs(roots[1], roots[0]);
  }
  vector < pair <int, pair <int, int> > > res;
  for (int i = 0; i < n; i++) {
    if (jobs[i].empty()) {
      continue;
    }
    int at = i;
    for (int &v : jobs[i]) {
      res.emplace_back(pv[i], make_pair(at, v));
      res.emplace_back(v, make_pair(pv[v], i));
      at = v;
    }
    res.emplace_back(pv[i], make_pair(at, i));
  }
  int cnt = res.size();
  printf("%d\n", cnt);
  for (int i = 0; i < cnt; i++) {
    printf("%d %d %d\n", res[i].first + 1, res[i].second.first + 1, res[i].second.second + 1);
  }
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i = a; i < (b); ++i)
#define rrep(i,a,b) for(int i = b; i --> (a);)
#define all(v) v.begin(),v.end()
#define trav(x,v) for(auto &x : v)
#define sz(v) (int)(v).size()
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;

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

	int n;
	cin >> n;
	vector<vi> gr(n);
	rep(i,1,n){
		int a, b;
		cin >> a >> b;
		--a, --b;
		gr[a].push_back(b);
		gr[b].push_back(a);
	}
	vi par(n, -1), sl(n, 1);
	function<void(int)> dfs1 = [&](int v){
		trav(u, gr[v]) if(u != par[v]){
			par[u] = v;
			dfs1(u);
			sl[v] += sl[u];
		}
	};
	dfs1(0);
	vi cs;
	rep(i,0,n){
		trav(j, gr[i]){
			int x = 0;
			if(j == par[i]) x = n - sl[i];
			else x = sl[j];
			if(2*x > n) goto done;
		}
		cs.push_back(i);
		done: ;
	}
	vi x, y, y2;
	int c = -1, pr = -1, d = -1;
	function<void(int,int)> dfs = [&](int v, int par){
		trav(u, gr[v]) if(u != par) dfs(u, v);
		x.push_back(c);
		y.push_back(pr);
		y2.push_back(v);
		pr = v;
		x.push_back(v);
		y.push_back(par);
		y2.push_back(d);
	};

	auto fun = [&](int anc, int v){
		c = anc;
		pr = v;
		d = v;
		trav(u, gr[v]) if(u != anc)
			trav(w, gr[u]) if(w != v)
				dfs(w, u);
		x.push_back(anc);
		y.push_back(pr);
		y2.push_back(v);
	};
	trav(i, cs) trav(j, gr[i])
		if(!count(all(cs), j))
			fun(i, j);

	cout << sz(x) << endl;
	rep(i,0,sz(x))
		cout << x[i]+1 << ' ' << y[i]+1 << ' ' << y2[i]+1 << endl;
}

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

using ll=long long;
#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
ll mask(int i){
	return (ll(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
	static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
	#endif
	return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
void myshuffle(vc<t>&a){
	rep(i,si(a))swap(a[i],a[rand_int(0,i)]);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

const int nmax=200010;
vi t[nmax];

vi cs;

int findc(int v,int p,int s){
	int ret=1,mx=0;
	for(auto to:t[v])if(to!=p){
		int f=findc(to,v,s);
		ret+=f;
		chmax(mx,f);
	}
	chmax(mx,s-ret);
	if(mx*2<=s){
		cs.pb(v);
	}
	return ret;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	int n;cin>>n;
	rep(_,n-1){
		int a,b;cin>>a>>b;
		a--;b--;
		t[a].pb(b);
		t[b].pb(a);
	}

	findc(0,-1,n);
	vc<pi> waf;
	for(auto c:cs){
		for(auto to:t[c]){
			bool ok=true;
			for(auto i:cs)if(i==to)ok=false;
			if(ok)waf.eb(to,c);
		}
	}

	vc<tuple<int,int,int>> ops;
	for(auto kv:waf){
		int x,y;tie(x,y)=kv;
		int tar=x;
		auto rec=[&](auto self,int v,int p)->void{
			if(v!=tar&&p!=tar){
				ops.eb(y,x,v);
				ops.eb(x=v,p,tar);
			}
			for(auto c:t[v])if(c!=p){
				self(self,c,v);
			}
		};
		rec(rec,x,y);
		ops.eb(y,x,tar);
	}

	print(si(ops));
	for(auto z:ops){
		int a,b,c;tie(a,b,c)=z;
		a++;b++;c++;
		print(a,2);
		print(b,2);
		print(c);
	}
}

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

#define ms(s, n) memset(s, n, sizeof(s))
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define FORd(i, a, b) for (int i = (a) - 1; i >= (b); i--)
#define FORall(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define sz(a) int((a).size())
#define present(t, x) (t.find(x) != t.end())
#define all(a) (a).begin(), (a).end()
#define uni(a) (a).erase(unique(all(a)), (a).end())
#define pb push_back
#define pf push_front
#define mp make_pair
#define fi first
#define se second
#define prec(n) fixed<<setprecision(n)
#define bit(n, i) (((n) >> (i)) & 1)
#define bitcount(n) __builtin_popcountll(n)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pi> vii;
const int MOD = (int) 1e9 + 7;
const int MOD2 = 1007681537;
const int INF = (int) 1e9;
const ll LINF = (ll) 1e18;
const ld PI = acos((ld) -1);
const ld EPS = 1e-9;
inline ll gcd(ll a, ll b) {ll r; while (b) {r = a % b; a = b; b = r;} return a;}
inline ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
inline ll fpow(ll n, ll k, int p = MOD) {ll r = 1; for (; k; k >>= 1) {if (k & 1) r = r * n % p; n = n * n % p;} return r;}
template<class T> inline int chkmin(T& a, const T& val) {return val < a ? a = val, 1 : 0;}
template<class T> inline int chkmax(T& a, const T& val) {return a < val ? a = val, 1 : 0;}
inline ll isqrt(ll k) {ll r = sqrt(k) + 1; while (r * r > k) r--; return r;}
inline ll icbrt(ll k) {ll r = cbrt(k) + 1; while (r * r * r > k) r--; return r;}
inline void addmod(int& a, int val, int p = MOD) {if ((a = (a + val)) >= p) a -= p;}
inline void submod(int& a, int val, int p = MOD) {if ((a = (a - val)) < 0) a += p;}
inline int mult(int a, int b, int p = MOD) {return (ll) a * b % p;}
inline int inv(int a, int p = MOD) {return fpow(a, p - 2, p);}
inline int sign(ld x) {return x < -EPS ? -1 : x > +EPS;}
inline int sign(ld x, ld y) {return sign(x - y);}
#define db(x) cerr << #x << " = " << (x) << " ";
#define endln cerr << "\n";

const int maxn = 2e5 + 5;
int n;
vi adj[maxn];
int del[maxn];
int size[maxn];

vector<pair<int, pi> > res;

void dfs(int u, int p) {
    size[u] = 1;
    for (int i = 0; i < adj[u].size(); i++) {
        int v = adj[u][i];
        if (v != p && !del[v]) {
            dfs(v, u);
            size[u] += size[v];
        }
    }
}
int findcentroid(int u) {
    int p = -1; dfs(u, -1);
    int cap = size[u] >> 1;
    while (1) {
        bool found = false;
        for (int i = 0; i < adj[u].size(); i++) {
            int v = adj[u][i];
            if (v != p && !del[v] && size[v] > cap) {
                found = true;
                p = u; u = v;
                break;
            }
        }
        if (!found) return u;
    }
}

int lst;

void dfs(int u, int p, int ac, int w) {
    FOR(i, 0, sz(adj[u])) {
        int v = adj[u][i];
        if (v != p) {
            dfs(v, u, ac, w);
            if (p != ac && u != w) {
                res.pb(mp(ac, mp(lst, v)));
                res.pb(mp(v, mp(u, w)));
                lst = v;
            }
        }
    }
}

void solve() {
    cin >> n;
    FOR(i, 0, n - 1) {
        int u, v; cin >> u >> v; u--, v--;
        adj[u].pb(v), adj[v].pb(u);
    }
    int u = findcentroid(0);
    int w = -1;
    FOR(i, 0, sz(adj[u])) {
        int v = adj[u][i];
        if (size[v] + size[v] == n) {
            w = v;
        }
    }
    if (w == -1) {
        FOR(i, 0, sz(adj[u])) {
            int v = adj[u][i];
            lst = v;
            dfs(v, u, u, v);
            if (lst != v) {
                res.pb(mp(u, mp(lst, v)));
            }
        }
    }
    else {
        FOR(it, 0, 2) {
            FOR(i, 0, sz(adj[u])) {
                int v = adj[u][i];
                if (v != w) {
                    lst = v;
                    dfs(v, u, u, v);
                    if (lst != v) {
                        res.pb(mp(u, mp(lst, v)));
                    }
                }
            }
            swap(u, w);
        }
    }
    cout << sz(res) << "\n";
    FOR(i, 0, sz(res)) {
        cout << res[i].fi + 1 << " " << res[i].se.fi + 1 << " " << res[i].se.se + 1 << "\n";
    }
}

int main() {
    int JUDGE_ONLINE = 1;
    if (fopen("in.txt", "r")) {
        JUDGE_ONLINE = 0;
        assert(freopen("in.txt", "r", stdin));
        //assert(freopen("out.txt", "w", stdout));
    }
    else {
        ios_base::sync_with_stdio(0), cin.tie(0);
    }
    solve();
    if (!JUDGE_ONLINE) {
        //cout << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
    }
    return 0;
}

#include <bits/stdc++.h>

using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ll long long
const int N = 1e6+5;
vector<int>g[N],p,gg[N];
vector<vector<int> >ans;
int size[N],n,f[N]={0},size_p[N]={0},V[N];
map<pair<int,int>,int>m;
vector<int>tmp;
vector<pair<int,int> >tmp1;
int dfs(int u,int fa)
{
	size[u]=1;
	for(auto &v:g[u]){if(v==fa)continue;size[u]+=dfs(v,u);}
	return size[u];
}
void dfs1(int u,int fa)
{
	for(auto &v:g[u]){if(v==fa)continue;dfs1(v,u);}
	int ma=n-size[u];
	for(auto &v:g[u]){if(v==fa)continue;ma=max(ma,size[v]);}
	if(ma*2<=n)p.pb(u);
}
void dfs2(int u,int fa)
{
	for(auto &v:g[u]){if(v==fa||2*size[v]==n)continue;dfs2(v,u);}
	int ff=fa;
	if(fa!=-1&&n-size[u]>size[u])for(auto &v:g[u]){if(v==fa)continue;
		if(!V[u])V[u]=f[v];
		ans.pb({ff,u,f[v]});
		m[{ff,u}]=m[{u,ff}]=0;m[{ff,f[v]}]=m[{f[v],ff}]=1;
		ff=(V[v]==0?v:V[v]);
	}f[u]=u;
}
int dfs4(int u,int fa)
{
	int t=u;
	for(auto &v:g[u]){if(v==fa)continue;t=dfs4(v,u);}
	if((int)g[u].size()==1)return u;
	if(fa!=-1) ans.pb({fa,u,t});
	return t;
}
int dfs5(int u,int fa)
{
	int si=1;
	for(auto &v:g[u]){if(v==fa)continue;si+=dfs5(v,u);}
	if(n%2==0){if(si==n/2){tmp.pb(fa),tmp.pb(u);}}
	else{if(si==n/2+1)tmp.pb(u);}
	return si;
}
int main()
{
	scanf("%d",&n);memset(V,0,sizeof(V));memset(f,0,sizeof(f));memset(size_p,0,sizeof(size_p));
	for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].pb(v);g[v].pb(u);}
	dfs(1,-1);dfs1(1,-1);
	for(int i=1;i<=n;i++)for(auto &v:g[i])m[{i,v}]=1;
	for(auto &t:p)dfs(t,-1),dfs2(t,-1);
	//for(auto &t:ans)printf("%d %d %d\n",t[0],t[1],t[2] );
	for(int i=1;i<=n;i++)g[i].clear();
	for(auto &t:m)if(t.se){g[t.fi.fi].pb(t.fi.se);size_p[t.fi.se]++;}
	dfs(1,-1);
	for(int i=1;i<=n;i++)if(size_p[i]>2)tmp.pb(i);
	if((int)tmp.size()==0){int tt;
		for(int i=1;i<=n;i++)if(size_p[i]==1){tt=i;break;}
		dfs5(tt,-1);
	}else{p.clear();
		dfs(1,-1);dfs1(1,-1);
		tmp.clear();for(auto &t:p)tmp.pb(t);
	}
	if((int)tmp.size()==1)for(auto &v:g[tmp[0]])tmp1.pb({v,tmp[0]});
	else{
		for(auto &v:g[tmp[0]])if(v!=tmp[1])tmp1.pb({v,tmp[0]});
		for(auto &v:g[tmp[1]])if(v!=tmp[0])tmp1.pb({v,tmp[1]});
	}
	for(auto &t:tmp1)dfs4(t.fi,t.se);
	printf("%d\n",(int)ans.size() );
	for(auto &t:ans)printf("%d %d %d\n",t[0],t[1],t[2] );
	return 0;
}
/*
10
1 4
1 5
1 6
1 2
2 10
10 3
3 7
3 8
3 9
*/

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <ctype.h>
#include <deque>
#include <queue>
#include <cstring>
#include <set>
#include <list>
#include <map>
#include <random>
#include <unordered_map>
#include <stdio.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef std::vector<int> vi;
typedef std::vector<bool> vb;
typedef std::vector<string> vs;
typedef std::vector<double> vd;
typedef std::vector<long long> vll;
typedef std::vector<std::vector<int> > vvi;
typedef vector<vll> vvll;
typedef std::vector<std::pair<int, int> > vpi;
typedef vector<vpi> vvpi;
typedef std::pair<int, int> pi;
typedef std::pair<ll, ll> pll;
typedef std::vector<pll> vpll;

const long long mod = 1000000007;

#define all(c) (c).begin(),(c).end()
#define forn(i, a, b) for(int i = a; i < b; i++)

#define pb push_back
#define mp make_pair
vvi nb;
vvi ch;
int n;
vi st;
vi par;
int root = -1;
int root2 = -1;
void dfs(int v, int p) {
    st[v] = 1;
    for(auto u : nb[v]) {
        if(u==p) continue;
        dfs(u,v);
        par[u] = v;
        st[v] += st[u];
        ch[v].pb(u);
    }
    if(root == -1 && 2*st[v] >= n) root = v;
}

vector<deque<int>> her;
vi ax, ay, ay2;

void straighten(int v, int p) {
    for(auto u : ch[v]) straighten(u, v);
    if(ch[v].empty()) her[v] = deque<int>(1,v);
    else {
        int mind = -1;
        int best = 0;
        for(auto u : ch[v]) if(her[u].size() > best) {
            best = her[u].size();
            mind = u;
        }
        int mu = mind;

        int curp = p;
        int curtop = v;
        vi indi;
        for(auto u : ch[v]) {
            if(u==mu) continue;
            ax.pb(curp);
            ay.pb(curtop);
            ay2.pb(her[u].back());
            curp = her[u].front();
            indi.pb(u);
        }
        her[v] = std::move(her[mu]);
        her[mu].clear();
        her[v].push_front(v);
        reverse(all(indi));
        for(auto ind : indi) {
            for(auto x : her[ind]) her[v].push_front(x);
        }
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.txt", "rt", stdin);
    freopen("output.txt", "wt", stdout);
#endif

    scanf("%d", &n);
    nb.resize(n);
    st.resize(n);
    par = vi(n,-1);
    forn(i,0,n-1) {
        int u,v;
        scanf("%d %d", &u, &v);
        u--; v--;
        nb[u].pb(v);
        nb[v].pb(u);
    }
    ch.clear();
    ch.resize(n);
    her.resize(n);
    dfs(0, -1);
    ch.clear();
    ch.resize(n);
    dfs(root,-1);
    forn(i,0,n) {
        if(i != root && 2*st[i] >= n) root2 = i;
    }
    for(auto x : ch[root]) if(x != root2) straighten(x, root);
    if(root2 != -1) for(auto x : ch[root2]) if(x != root) straighten(x,root2);
    for(auto x : ch[root]) if(x!=root2) {
        if(her[x].size() > 2) {
            her[x].push_front(root);
            int k = her[x].size();
            for(int i = k-4; i>=0; i--) {
                ax.pb(her[x][i]);
                ay.pb(her[x][i+1]);
                ay2.pb(her[x][k-2]);
            }
        }
    }
    if(root2 != -1) for(auto x : ch[root2]) if(x != root) {
        if(her[x].size() > 2) {
            her[x].push_front(root2);
            int k = her[x].size();
            for(int i = k-4; i>=0; i--) {
                ax.pb(her[x][i]);
                ay.pb(her[x][i+1]);
                ay2.pb(her[x][k-2]);
            }
        }
    }
    printf("%d\n", ax.size());
    forn(i,0,ax.size()) printf("%d %d %d\n", ax[i]+1, ay[i]+1, ay2[i]+1);

}

#pragma comment(linker, "/stack:20000000")
#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")

#define _CRT_SECURE_NO_WARNINGS
# include <iostream>
# include <cmath>
# include <algorithm>
# include <stdio.h>
# include <cstring>
# include <string>
# include <cstdlib>
# include <vector>
# include <bitset>
# include <map>
# include <queue>
# include <ctime>
# include <stack>
# include <set>
# include <list>
# include <random>
# include <deque>
# include <functional>
# include <iomanip>
# include <sstream>
# include <fstream>
# include <complex>
# include <numeric>
# include <immintrin.h>
# include <cassert>
# include <array>

using namespace std;

// Let's define unordered map
# ifdef __GNUC__
# if __cplusplus > 199711L
# include <unordered_set>
# include <unordered_map>
# else
# include <tr1/unordered_map>
# include <tr1/unordered_set>
using namespace tr1;
# endif
# else
# include <unordered_map>
# include <unordered_set>
# endif

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL_((0,__VA_ARGS__, 6,5,4,3,2,1))
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5,_6,N,...) N
#define macro_dispatcher(macro, ...) macro_dispatcher_(macro, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(macro, nargs) macro_dispatcher__(macro, nargs)
#define macro_dispatcher__(macro, nargs) macro_dispatcher___(macro, nargs)
#define macro_dispatcher___(macro, nargs) macro ## nargs
#define DBN1(a)           cerr<<#a<<"="<<(a)<<"\n"
#define DBN2(a,b)         cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBN3(a,b,c)       cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"
#define DBN4(a,b,c,d)     cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<"\n"
#define DBN5(a,b,c,d,e)   cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<"\n"
#define DBN6(a,b,c,d,e,f) cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<", "<<#f<<"="<<(f)<<"\n"
#define DBN(...) macro_dispatcher(DBN, __VA_ARGS__)(__VA_ARGS__)
#define DA(a,n) cerr<<#a<<"=["; printarray(a,n); cerr<<"]\n"
#define DAR(a,n,s) cerr<<#a<<"["<<s<<"-"<<n-1<<"]=["; printarray(a,n,s); cerr<<"]\n"

#ifdef _MSC_VER
#define ALIGN(x) __declspec(align(x))
#define PREFETCH(ptr, rw, level) ((void)0)
#else
#define ALIGN(x) __attribute__((aligned(x)))
#define PREFETCH(ptr, rw, level) __builtin_prefetch(ptr, rw, level)
#endif

#ifdef LOCAL
#define CURTIME() cerr << clock() * 1.0 / CLOCKS_PER_SEC << endl
#else
#define CURTIME() ;
#endif
double __begin;
#define DTIME(ccc) __begin = clock(); ccc; cerr<<"Time of work = "<<(clock()-__begin)/CLOCKS_PER_SEC<<endl;

#define mp make_pair
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef int itn;

template<class T1, class T2, class T3>
struct triple{ T1 a; T2 b; T3 c; triple() : a(T1()), b(T2()), c(T3()) {}; triple(T1 _a, T2 _b, T3 _c) :a(_a), b(_b), c(_c){} };
template<class T1, class T2, class T3>
bool operator<(const triple<T1,T2,T3>&t1,const triple<T1,T2,T3>&t2){if(t1.a!=t2.a)return t1.a<t2.a;else if(t1.b!=t2.b)return t1.b<t2.b;else return t1.c<t2.c;}
template<class T1, class T2, class T3>
bool operator>(const triple<T1,T2,T3>&t1,const triple<T1,T2,T3>&t2){if(t1.a!=t2.a)return t1.a>t2.a;else if(t1.b!=t2.b)return t1.b>t2.b;else return t1.c>t2.c;}
#define tri triple<int,int,int>
#define trll triple<ll,ll,ll>

#define FI(n) for(int i=0;i<n;++i)
#define FJ(n) for(int j=0;j<n;++j)
#define FK(n) for(int k=0;k<n;++k)
#define FL(n) for(int l=0;l<n;++l)
#define FQ(n) for(int q=0;q<n;++q)
#define FOR(i,a,b) for(int i = (a), __e = (int) (b); i < __e; ++i)
#define all(a) std::begin(a), std::end(a)
#define reunique(v) v.resize(unique(v.begin(), v.end()) - v.begin())

#define sqr(x) ((x) * (x))
#define sqrt(x) sqrt(1.0 * (x))
#define pow(x, n) pow(1.0 * (x), n)

#define COMPARE(obj) [&](const std::decay<decltype(obj)>::type& a, const std::decay<decltype(obj)>::type& b)
#define COMPARE_BY(obj, field) [&](const std::decay<decltype(obj)>::type& a, const std::decay<decltype(obj)>::type& b) { return a.field < b.field; }

#define checkbit(n, b) (((n) >> (b)) & 1)
#define setbit(n, b) ((n) | (static_cast<std::decay<decltype(n)>::type>(1) << (b)))
#define removebit(n, b) ((n) & ~(static_cast<std::decay<decltype(n)>::type>(1) << (b)))
#define flipbit(n, b) ((n) ^ (static_cast<std::decay<decltype(n)>::type>(1) << (b)))
inline int bits_count(int v){v=v-((v>>1)&0x55555555);v=(v&0x33333333)+((v>>2)&0x33333333);return((v+(v>>4)&0xF0F0F0F)*0x1010101)>>24;}
inline int bits_count(ll v){int t=v>>32;int p=(v& ((1LL << 32) - 1)); return bits_count(t) + bits_count(p); }
unsigned int reverse_bits(register unsigned int x){ x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); return((x >> 16) | (x << 16)); }
template<class T>
inline int sign(T x){ return x > 0 ? 1 : x < 0 ? -1 : 0; }
inline bool isPowerOfTwo(int x){ return (x != 0 && (x&(x - 1)) == 0); }
template<class T1, class T2, class T3> T1 inline clamp(T1 x, const T2& a, const T3& b) { if (x < a) return a; else if (x > b) return b; else return x; }
unsigned long long rdtsc() {
#ifdef _MSC_VER
    return 0;
#else
    unsigned long long ret;
    __asm__ __volatile__("rdtsc" : "=A" (ret) : :);
    return ret;
#endif
}
// Fast IO ********************************************************************************************************
template<class T = int> T read_int() {
    const int B = 4096;
    static char b[B + 16], *e = b + B, *i = e;
    auto c = [&]() { if (i == e) memset(b, 0, B), cin.read(b, B), i = b; };
    c();
    while (*i && (*i < '0' || *i > '9') && *i != '-') ++i;
    c();
    bool m = false;
    if (*i == '-') ++i, c(), m = true;
    T r = 0;
    while (*i >= '0' && *i <= '9') r = r * 10 + *i - '0', ++i, c();
    ++i;
    return m ? -r : r;
}
template<class T>
void write_int(T x, char endc = '\n') {
    const int B = 4096;
    static char b[B + 20], *i = b, *e = b + B;
    if (x < 0) *i++ = '-', x = -x;
    if (x == 0) *i++ = '0';
    char* s = i;
    while (x) {
        T t = x / 10;
        char c = x - 10 * t + '0';
        *i++ = c;
        x = t;
    }
    char* f = i - 1;
    while (s < f) swap(*s, *f), ++s, --f;
    if (i > e) cout.write(b, i - b), i = b;
    *i++ = endc;
    struct F { ~F() { if (i != b) cout.write(b, i - b); } };
    static F flush;
}

//STL output *****************************************************************************************************
#define TT1 template<class T>
#define TT1T2 template<class T1, class T2>
#define TT1T2T3 template<class T1, class T2, class T3>
TT1T2 ostream& operator << (ostream& os, const pair<T1, T2>& p);
TT1 ostream& operator << (ostream& os, const vector<T>& v);
TT1T2 ostream& operator << (ostream& os, const set<T1, T2>&v);
TT1T2 ostream& operator << (ostream& os, const multiset<T1, T2>&v);
TT1T2 ostream& operator << (ostream& os, priority_queue<T1, T2> v);
TT1T2T3 ostream& operator << (ostream& os, const map<T1, T2, T3>& v);
TT1T2T3 ostream& operator << (ostream& os, const multimap<T1, T2, T3>& v);
TT1T2T3 ostream& operator << (ostream& os, const triple<T1, T2, T3>& t);
TT1T2 ostream& operator << (ostream& os, const pair<T1, T2>& p){ return os <<"("<<p.first<<", "<< p.second<<")"; }
TT1 ostream& operator << (ostream& os, const vector<T>& v){       bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const set<T1, T2>&v){    bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multiset<T1,T2>&v){bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2T3 ostream& operator << (ostream& os, const map<T1,T2,T3>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multimap<T1, T2>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, priority_queue<T1, T2> v) { bool f = 1; os << "["; while (!v.empty()) { auto x = v.top(); v.pop(); if (!f) os << ", "; f = 0; os << x; } return os << "]"; }
TT1T2T3 ostream& operator << (ostream& os, const triple<T1, T2, T3>& t){ return os << "(" << t.a << ", " << t.b << ", " << t.c << ")"; }
TT1T2 void printarray(T1 a, T2 sz, T2 beg = 0){ for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }

//STL input *****************************************************************************************************
TT1T2T3 inline istream& operator >> (istream& os, triple<T1, T2, T3>& t);
TT1T2 inline istream& operator >> (istream& os, pair<T1, T2>& p) { return os >> p.first >> p.second; }
TT1 inline istream& operator >> (istream& os, vector<T>& v) {
    if (v.size()) for (T& t : v) os >> t; else {
        string s; T obj; while (s.empty()) {getline(os, s); if (!os) return os;}
        stringstream ss(s); while (ss >> obj) v.push_back(obj);
    }
    return os;
}
TT1T2T3 inline istream& operator >> (istream& os, triple<T1, T2, T3>& t) { return os >> t.a >> t.b >> t.c; }

//Pair magic *****************************************************************************************************
#define PT1T2 pair<T1, T2>
TT1T2 inline PT1T2 operator+(const PT1T2 &p1 , const PT1T2 &p2) { return PT1T2(p1.first + p2.first, p1.second + p2.second); }
TT1T2 inline PT1T2 operator-(const PT1T2 &p1 , const PT1T2 &p2) { return PT1T2(p1.first - p2.first, p1.second - p2.second); }

#undef TT1
#undef TT1T2
#undef TT1T2T3

#define FREIN(FILE) freopen(FILE, "rt", stdin)
#define FREOUT(FILE) freopen(FILE, "wt", stdout)

template<class T> inline void normmod(T &x, T m) { x %= m; if (x < 0) x += m; }
template<class T1, class T2> inline T2 summodfast(T1 x, T1 y, T2 m) { T2 res = x + y; if (res >= m) res -= m; return res; }
template<class T1, class T2, class T3> inline void addmodfast(T1 &x, T2 y, T3 m) { x += y; if (x >= m) x -= m; }
template<class T1, class T2, class T3> inline void submodfast(T1 &x, T2 y, T3 m) { x -= y; if (x < 0) x += m; }
inline ll mulmod(ll x, ll n, ll m){ ll r = 0; normmod(x, m); normmod(n, m); while (n) { if (n & 1) addmodfast(r, x, m); addmodfast(x, x, m); n /= 2; } return r; }
inline ll mulmodfast(ll x, ll n, ll m){ ll r = 0; while (n){ if (n & 1) addmodfast(r, x, m); addmodfast(x, x, m); n /= 2; } return r; }
inline ll powmod(ll x, ll n, ll m){ ll r = 1; normmod(x, m); while (n){ if (n & 1)r = (r*x) % m; x = (x*x) % m; n /= 2; }return r; }
inline ll powmulmod(ll x, ll n, ll m) { ll res = 1; normmod(x, m); while (n){ if (n & 1)res = mulmod(res, x, m); x = mulmod(x, x, m); n /= 2; } return res; }
template<class T> inline T gcd(T a, T b) { while (b) { a %= b; T t = a; a = b; b = t; } return a; }
inline ll lcm(ll a, ll b){ return a / gcd(a, b) * b; }
template<class T> inline T gcd(T a, T b, T c){ return gcd(gcd(a, b), c); }
ll gcdex(ll a, ll b, ll& x, ll& y) {
    if (!a) { x = 0; y = 1; return b; }
    ll y1; ll d = gcdex(b % a, a, y, y1); x = y1 - (b / a) * y;
    return d;
}
template<class T> bool isPrime(T x) { if (x < 2) return 0; for (T i = 2; i * i <= x; ++i) if (x % i == 0) return 0; return 1; }
bool millerRabin(long long n) {
    if (n <= 2) return n == 2;
    long long s = n - 1; int t = 0; while (s % 2 == 0) s /= 2, ++t;
    for (int a : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}) { if (a >= n) return a == n;
        long long f = powmulmod(a, s, n); if (f == 1 || f == n - 1) continue;
        for (int i = 1; i < t; ++i) if ((f = mulmodfast(f, f, n)) == n - 1) goto nextp;
        return false; nextp:;
    } return true;
}

// Useful constants

//int some_primes[7] = {24443, 100271, 1000003, 1000333, 5000321, 98765431, 1000000123};
#define INF         1011111111
#define LLINF       1000111000111000111LL
#define EPS         (double)1e-10
#define mod         1000000007
#define PI          3.14159265358979323
#define link        asaxlajrewqwe
#define rank        wahayawehasdakw
//*************************************************************************************

//vector<int> v[201010];
set<int> g[202020];
int ct;
vector<int> c;
int sz[202020];
int used[202020];
int n;
vector<tri> ans;
void go(int cur, int iter = 1) {
//    DBN(cur, iter);
    sz[cur] = 1;
    used[cur] = iter;
    int t = 0;
    for (int to : g[cur]) {
        if (used[to] != iter) {
            go(to, iter);
            sz[cur] += sz[to];
            t = max(t, sz[to]);
        }
    }
    t = max(t, n - sz[cur]);
    if (t * 2 <= n) {
        ct = cur;
        c.push_back(cur);
    }
}
vector<pii> st;
void dfs2(int cur, int p = -1) {
    used[cur] = true;
    for (int to : g[cur]) {
        if (!used[to] ){
            dfs2(to, cur);
        }
    }
    st.push_back({cur, p});
}
void solve(int cur) {
    st.clear();
    dfs2(cur);
    st.pop_back();
    int last = cur;
    for (pii p : st) {
        int v = p.first;
        int par = p.second;
        if (par != cur) {
            ans.push_back({ct, last, v});
            ans.push_back({v, par, cur});
            last = v;
        }
    }
    if (last != cur) {
        ans.push_back({ct, last, cur});
    }
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#ifdef LOCAL
//    FREIN("input.txt");
#endif
    cin >> n;
    FI(n - 1) {
        int x, y;
        cin >> x >> y;
//        v[x].push_back(y);
        g[x].insert(y);
//        v[y].push_back(x);
        g[y].insert(x);
    }
    go(1);
    memset(used, 0, sizeof(used));
    assert(c.size() > 0);
    for (int x : c) {
        used[x] = true;
    }
    for (int x : c) {
        ct = x;
        for (int to : g[ct]) {
            if (!used[to]) {
                solve(to);
            }
        }
    }
    cout << ans.size() << endl;
    assert(ans.size() <= 2 * n);
    for (auto t : ans) {
//        assert(g[t.a].count(t.b));
//        g[t.a].erase(t.b);
//        g[t.a].insert(t.c);
//        assert(g[t.b].count(t.a));
//        g[t.b].erase(t.a);
//        g[t.c].insert(t.a);
        cout << t.a << ' ' << t.b << ' ' << t.c << '\n';
    }
//    FI(n) {
//        DBN(i + 1, g[i + 1]);
//    }
    return 0;
}

/*

 5 3 80
 97 -1
 58 5
 16 2
 81 1
 79 4

 */

///****In the name of ALLAH, most Gracious, most Compassionate****//

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

typedef long long ll;
typedef pair <int, int> pii;

#define ALL(a) a.begin(), a.end()
#define FastIO ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define IN freopen("input.txt","r+",stdin)
#define OUT freopen("output.txt","w+",stdout)

#define DBG(a) cerr<< "line "<<__LINE__ <<" : "<< #a <<" --> "<<(a)<<endl
#define NL cout<<endl

template < class T1,class T2>
ostream &operator <<(ostream &os,const pair < T1,T2 > &p)
{
    os<<"{"<<p.first<<","<<p.second<<"}";
    return os;
}

const int N=3e5+5;
const int oo=1e9+7;

set<int > g[N];
int sz[N];

vector< tuple < int, int, int > > ans;

int dfs_sz(int u,int  p )
{
    sz[u] = 1;
    for(int v: g[u])
        if(v!=p)
            sz[u]+=dfs_sz(v,u);
    return sz[u];
}
int find_centroid(int u,int  p,int size)
{
    for(int v: g[u])
        if(v!=p and sz[v] > size / 2)
            return find_centroid(v,u,size );
    return u;
}

int make_centroid_tree(int u)
{
    int size = dfs_sz(u,u);
    u= find_centroid(u,u,size);
    return u;
}

int find_leaf(int u, int p = -1)
{
    for(int v: g[u])
        if(v!=p)
            return find_leaf(v);
    return u;
}

vector<int > chain;

void make_chain(int u,int p,int &uu,int &vv)
{
    for(int v: g[u])
        if(v!=p)
            make_chain(v,u,uu,vv);
    chain.push_back(u);
    if(u!=vv)
        ans.push_back(make_tuple(uu,vv,u));
    uu=u,vv = p;
}

void make_star(int u)
{
    int n =chain.size();
    for(int i=n-4; i>=0; i--)
    {
        ans.push_back(make_tuple(chain[i], chain[i+1], chain[n-2]));
    }
    if(n>=3)
        ans.push_back(make_tuple(u,chain.front(), chain[n - 2]));
}

int32_t main()
{
    FastIO;
    int n;
    cin>>n;
    for(int i=1; i<=n-1; i++)
    {
        int u,v;
        cin>>u>>v;
        g[u].insert(v);
        g[v].insert(u);
    }
    int centroid = make_centroid_tree(1);

    for(int v: g[centroid])
    {
        g[v].erase(centroid);
        int size = dfs_sz(v,centroid);
        if( n- size <= size )
        {
            int centroid = v;
            for(int v: g[centroid])
            {
                g[v].erase(centroid);
                chain.clear();
                int uu = centroid, vv = v;
                make_chain(v,centroid, uu,vv);
                make_star(centroid);
            }
        }
        else
        {

            chain.clear();
            int uu = centroid, vv = v;
            make_chain(v,centroid, uu,vv);
            make_star(centroid);

        }
//        DBG(&chain);
//        for(int u: chain) cout<<u<<" "; NL;
    }

    cout<<ans.size()<<"\n";
    for(auto i: ans)
    {
        cout<<get<0>(i)<<" ";
        cout<<get<1>(i)<<" ";
        cout<<get<2>(i)<<"\n";
    }
}

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

#define N 202020

int n, sos[N], pa[N];

vector<int> v[N], u[N];

void dfs(int rt) {
	if (rt != 1 && v[rt].size() == 1) {
		sos[rt] = 1;
		return;
	}
	sos[rt] = 1;
    for (int i = 0; i < v[rt].size(); i ++) if (v[rt][i] != pa[rt]) {
		pa[v[rt][i]] = rt;
		dfs(v[rt][i]);
		sos[rt] += sos[v[rt][i]];
    }
}

int cnt;
int ansx[N*2], ansy[N*2], ansz[N*2];

void putans() {
	printf("%d\n", cnt);
	for (int i = 1; i <= cnt; i ++) printf("%d %d %d\n", ansx[i], ansy[i], ansz[i]);
}

void oper(int x, int y, int z) {
	ansx[++cnt] = x;
	ansy[cnt] = y;
	ansz[cnt] = z;
}

int curx[N], cury[N];
int q[N];

bool ok(int rt) {
	if (sos[rt] * 2 <= n) return 0;
	for (int i = 0; i < v[rt].size(); i ++) if (v[rt][i] != pa[rt]) {
		if (sos[v[rt][i]] * 2 >= n) return 0;
	}
	return 1;
}

void DFS(int rt) {
    for (int i = 0; i < v[rt].size(); i ++) if (v[rt][i] != pa[rt]) {
		pa[v[rt][i]] = rt;
		DFS(v[rt][i]);
    }
}

void bfs(int rt, int wi) {
	int e = 0;
	q[++e] = rt;
	for (int f = 1; f <= e; f ++) {
		for (int i = 0; i < v[q[f]].size(); i ++) if (pa[q[f]] != v[q[f]][i]) {
			q[++e] = v[q[f]][i];
		}
	}
	int now = rt;
	for (int i = 2; i <= e; i ++) {
		oper(wi, now, q[i]);
		now = q[i];
		oper(now, pa[now], rt);
	}
	oper(wi, now, rt);
}

void solve(int rt) {
	memset(pa, 0, sizeof pa);
	DFS(rt);
	for (int i = 0; i < v[rt].size(); i ++) {
        bfs(v[rt][i], rt);
	}
}

void bfs1(int rt) {
	int e = 0;
	q[++e] = rt;
	for (int f = 1; f <= e; f ++) {
		for (int i = 0; i < v[q[f]].size(); i ++) if (pa[q[f]] != v[q[f]][i]) {
			q[++e] = v[q[f]][i];
		}
	}
	int to = q[2];
	int now = to;
	for (int i = 3; i <= e; i ++) {
		if (pa[q[i]] == rt) continue;
		oper(rt, now, q[i]);
		now = q[i];
		oper(now, pa[q[i]], to);
	}
	oper(rt, now, to);
}

void new_solve(int rt, int rt2) {
	memset(pa, 0, sizeof pa);
	pa[rt] = rt2;
	pa[rt2] = rt;
	DFS(rt);
	DFS(rt2);
	for (int i = 0; i < v[rt].size(); i ++) if (v[rt][i] != rt2) {
		bfs(v[rt][i], rt);
	}
	for (int i = 0; i < v[rt2].size(); i ++) if (v[rt2][i] != rt) {
		bfs(v[rt2][i], rt2);
	}
}

int main() {//freopen("r.in", "r", stdin);
	scanf("%d", &n);
	for (int i = 1, x, y; i < n; i ++) {
		scanf("%d %d", &x, &y);
		v[x].push_back(y);
		v[y].push_back(x);
	}
	if (n <= 4) {
		puts("0");
		return 0;
	}
	pa[1] = 0;
	dfs(1);
	bool flag = 0;
	for (int i = 1; i <= n && !flag; i ++) {
		if (ok(i)) {
			solve(i);
			flag = 1;
		}
	}
	if (!flag) {
		for (int i = 1; i <= n && !flag; i ++) {
            if (sos[i] * 2 == n) {
				new_solve(i, pa[i]);
				flag = 1;
            }
		}
	}
	assert(flag);
	putans();
	return 0;
}

#ifdef DEBUG
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <cassert>
#include <sstream>
#include <fstream>
#include <functional>
#include <set>
#include <bitset>
#include <string>
#include <utility>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#else
#include <bits/stdc++.h>
#endif

#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif

#define rep(i, n) for (int i = 0, i##_end_ = (n); i < i##_end_; ++i)
#define per(i, n) for (int i = (n) - 1; i >= 0; --i)
#define forn(i, l, r) for (int i = (l), i##_end_ = (r); i <= i##_end_; ++i)
#define nrof(i, r, l) for (int i = (r), i##_end_ = (l); i >= i##_end_; --i)
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define SZ(x) (int)((x).size())
#define ALL(x) (x).begin(), (x).end()

using namespace std;

typedef vector<int> vi;

typedef pair<int, int> pii;

typedef long long LL;

template<typename T> inline bool chkmax(T &x, const T &y) {
	return x < y ? x = y, 1 : 0;
}

#ifdef DEBUG
char *input_file, *output_file;
#endif

struct IO {
	static const int maxn = (1 << 25) + 10;

	char a[maxn], *s, b[maxn], *t;

	void INPUT() {
		s = a;
		t = b;
		#ifdef DEBUG
		FILE *f = fopen(input_file, "r");
		a[fread(a, 1, sizeof a, f)] = 0;
		#else
		a[fread(a, 1, sizeof a, stdin)] = 0;
		#endif
	}

	void OUTPUT() {
#ifdef DEBUG
		FILE *f = fopen(output_file, "w");
		fwrite(b, 1, t - b, f);
#else
		fwrite(b, 1, t - b, stdout);
#endif
	}

	operator int() {
		int x = 0;
		while(*s != '-' && (*s < '0' || *s > '9')) {
			++s;
		}
		bool f = 0;
		if(*s == '-') {
			f = 1;
			++s;
		}
		while(*s >= '0' && *s <= '9') {
			(x *= 10) += *s - '0';
			++s;
		}
		if(f) {
			x = -x;
		}
		return x;
	}

	operator LL() {
		LL x = 0;
		while(*s != '-' && (*s < '0' || *s > '9')) {
			++s;
		}
		bool f = 0;
		if(*s == '-') {
			f = 1;
			++s;
		}
		while(*s >= '0' && *s <= '9') {
			(x *= 10) += *s - '0';
			++s;
		}
		if(f) {
			x = -x;
		}
		return x;
	}

	operator char() {
		while(*s <= 32) {
			++s;
		}
		char ret = *s;
		++s;
		return ret;
	}

	inline void out(int x) {
		if(!x) {
			*t++ = '0';
			return;
		}
		if(x < 0) {
			*t++ = '-';
			x = -x;
		}
		static char c[20], *i;
		i = c;
		while(x) {
			int y = x / 10;
			*i++ = x - y * 10 + '0';
			x = y;
		}
		while(i != c) {
			*t++ = *--i;
		}
		return;
	}

	inline void out(int x, char C) {
		if(!x) {
			*t++ = '0';
			*t++ = C;
			return;
		}
		if(x < 0) {
			*t++ = '-';
			x = -x;
		}
		static char c[20], *i;
		i = c;
		while(x) {
			int y = x / 10;
			*i++ = x - y * 10 + '0';
			x = y;
		}
		while(i != c) {
			*t++ = *--i;
		}
		*t++ = C;
		return;
	}

	inline void out(LL x) {
		if(!x) {
			*t++ = '0';
			return;
		}
		if(x < 0) {
			*t++ = '-';
			x = -x;
		}
		static char c[20], *i;
		i = c;
		while(x) {
			LL y = x / 10;
			*i++ = x - y * 10 + '0';
			x = y;
		}
		while(i != c) {
			*t++ = *--i;
		}
		return;
	}

	inline void out(LL x, char C) {
		if(!x) {
			*t++ = '0';
			*t++ = C;
			return;
		}
		if(x < 0) {
			*t++ = '-';
			x = -x;
		}
		static char c[20], *i;
		i = c;
		while(x) {
			LL y = x / 10;
			*i++ = x - y * 10 + '0';
			x = y;
		}
		while(i != c) {
			*t++ = *--i;
		}
		*t++ = C;
		return;
	}

	inline void out(char c) {
		*t++ = c;
		return;
	}
}io;

void Main();

int main(int argc, char *argv[]) {
#ifdef DEBUG
	input_file = argv[1];
	output_file = argv[2];
#endif
	io.INPUT();
	Main();
	io.OUTPUT();
	return 0;
}

//---------------------------------------------------------------------------------------head---------------------------------------------------------------------------------------

const int maxn = 2e5 + 100;

int n, root1, root2;
vi g[maxn];
vector<pair<int, pii> > ans;
int sz[maxn], par[maxn], hs[maxn], dep[maxn], dp[maxn], rem[maxn];
bool vis[maxn];

int find_centroid() {
	static int q[maxn], fnt, rar;
	fnt = rar = 0;
	q[rar++] = 1;
	par[1] = 0;
	while(fnt != rar) {
		int u = q[fnt++];
		for (int v: g[u]) {
			if(v != par[u]) {
				q[rar++] = v;
				par[v] = u;
			}
		}
		sz[u] = 1;
		hs[u] = 0;
	}
	per(i, rar) {
		int u = q[i], v = par[u];
		chkmax(hs[u], n - sz[u]);
		if((hs[u] << 1) <= n) {
			return u;
		}
		sz[v] += sz[u];
		chkmax(hs[v], sz[u]);
	}
}

void dfs1(int u, int p = 0) {
	sz[u] = 1;
	for (int v: g[u]) {
		if(v != p) {
			dfs1(v, u);
			sz[u] += sz[v];
		}
	}
	return;
}

void solve(int rt, int fa) {
	static int q[maxn], fnt, rar;
	fnt = rar = 0;
	q[rar++] = rt;
	par[rt] = fa;
	while(fnt != rar) {
		int u = q[fnt++];
		for (int v: g[u]) {
			if(v != par[u]) {
				q[rar++] = v;
				par[v] = u;
			}
		}
	}
	reverse(q, q + rar);
	if(rt != q[0]) {
		ans.pb(mp(fa, mp(rt, q[0])));
	}
	rep(i, rar - 1) {
		int u = q[i], v = q[i + 1], w = par[u];
		if(v != w) {
			ans.pb(mp(u, mp(w, v)));
		}
	}
	per(i, rar - 2) {
		int u = q[i], v = q[i + 1], w = q[rar - 1];
		if(v != w) {
			ans.pb(mp(u, mp(v, w)));
		}
	}
	if(q[0] != q[rar - 1]) {
		ans.pb(mp(fa, mp(q[0], q[rar - 1])));
	}
	return;
}

void make(int rt, int fa) {
	for (int u: g[rt]) {
		if(u != fa) {
			solve(u, rt);
		}
	}
	return;
}

void Main() {
	n = io;
	rep(i, n - 1) {
		int u = io, v = io;
		g[u].pb(v);
		g[v].pb(u);
	}
	root1 = find_centroid();
	dfs1(root1);
	for (int u: g[root1]) {
		if((sz[u] << 1) == n) {
			root2 = u;
			break;
		}
	}
	make(root1, root2);
	if(root2) {
		make(root2, root1);
	}
	io.out(SZ(ans), '\n');
	for(auto x: ans) {
		io.out(x.X, ' ');
		io.out(x.Y.X, ' ');
		io.out(x.Y.Y, '\n');
	}
	return;
}

#include <bits/stdc++.h>
#define ADD(a, b) a = (a + ll(b)) % mod
#define MUL(a, b) a = (a * ll(b)) % mod
#define MAX(a, b) a = max(a, b)
#define MIN(a, b) a = min(a, b)
#define rep(i, a, b) for(int i = int(a); i < int(b); i++)
#define rer(i, a, b) for(int i = int(a) - 1; i >= int(b); i--)
#define all(a) (a).begin(), (a).end()
#define sz(v) (int)(v).size()
#define pb push_back
#define sec second
#define fst first
#define debug(fmt, ...) Debug(__LINE__, ":", fmt, ##__VA_ARGS__)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pi;
typedef pair<ll, ll> pl;
typedef pair<int, pi> ppi;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vl> mat;
typedef complex<double> comp;
void Debug() {cout << '\n'; }
template<class FIRST, class... REST>void Debug(FIRST arg, REST... rest){
	cout<<arg<<" ";Debug(rest...);}
template<class T>ostream& operator<<(ostream& out,const vector<T>& v) {
	out<<"[";if(!v.empty()){rep(i,0,sz(v)-1)out<<v[i]<<", ";out<<v.back();}out<<"]";return out;}
template<class S, class T>ostream& operator<<(ostream& out,const pair<S, T>& v){
	out<<"("<<v.first<<", "<<v.second<<")";return out;}
const int MAX_N = 200010;
const int MAX_V = 100010;
const double eps = 1e-6;
const ll mod = 1000000007;
const int inf = 1 << 29;
const ll linf = 1LL << 60;
const double PI = 3.14159265358979323846;
///////////////////////////////////////////////////////////////////////////////////////////////////

int N;
vector<int> G[MAX_N];
int S[MAX_N];
bool cen[MAX_N];
vector<int> C;
vector<int> sub[MAX_N], pre[MAX_N];
vector<vi> ans;

int dfs(int v, int p) {
	int cnt = 1;
	bool ok = true;
	rep(i, 0, sz(G[v])) {
		int n = G[v][i];
		if(n == p) continue;
		int a = dfs(n, v);
		if(a > N / 2) ok = false;
		cnt += a;
	}
	if(N - cnt > N / 2) ok = false;
	if(ok) {
		C.pb(v);
		cen[v] = true;
	}
	return cnt;
}

void dfs2(int v, int p, int c) {
	if(v != c && p != c) {
		sub[c].pb(v);
		pre[c].pb(p);
	}
	rep(i, 0, sz(G[v])) {
		int n = G[v][i];
		if(p == n) continue;
		dfs2(n, v, c);
	}
}

void solve() {
	cin >> N;
	rep(i, 0, N - 1) {
		int a, b; cin >> a >> b; a--; b--;
		G[a].pb(b);
		G[b].pb(a);
	}
	dfs(0, -1);
	// debug(C);
	rep(i, 0, sz(C)) {
		int v = C[i];
		rep(j, 0, sz(G[v])) {
			int n = G[v][j];
			if(cen[n]) continue;
			dfs2(n, v, n);

			int k = sz(sub[n]);
			if(k == 0) continue;
			ans.pb({v, n, sub[n][0]});
			rep(j, 0, k - 1) {
				int a = sub[n][j], b = pre[n][j], c = sub[n][j + 1];
				ans.pb({a, b, n});
				ans.pb({v, a, c});
			}
			int a = sub[n][k - 1], b = pre[n][k - 1];
			ans.pb({a, b, n});
			ans.pb({v, a, n});
		}
	}
	cout << sz(ans) << "\n";
	rep(i, 0, sz(ans)) {
		cout << ans[i][0] + 1 << " " << ans[i][1] + 1 << " " << ans[i][2] + 1 << "\n";
	}
}

int main() {
#ifndef LOCAL
	ios::sync_with_stdio(false);
    cin.tie(0);
#endif
    cout << fixed;
	cout.precision(20);
#ifdef LOCAL
    freopen("in.txt", "rt", stdin);
#endif
	solve();
#ifdef LOCAL
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
	return 0;
}

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

typedef int arr32[maxn];
arr32 fst, size, fa, que, done, nex, du, tmp;
int n, e, top;
vector <int> vec[maxn];
stack <int> sta;

struct str { int v, nex; } edge[maxn << 1];

struct ANS { int a, b, c; } ans[maxn << 1];

void make_edge(int a, int b) {
	du[a]++; du[b]++;
	edge[++e].nex = fst[a]; fst[a] = e; edge[e].v = b;
	edge[++e].nex = fst[b]; fst[b] = e; edge[e].v = a;
}

vector <int> bfs(int base) {
	int L = 0, R = 0;
	que[++R] = base;
	int Sing = 1 << 30;
	fa[base] = 0;
	while (L < R) {
		int u = que[++L];
		for (int i = fst[u]; i; i = edge[i].nex) {
			int v = edge[i].v;
			if (done[v]) continue;
			if (fa[u] == v) continue;
			fa[v] = u;
			que[++R] = v;
		}
	}

	for (int t = R; t; t--) {
		int u = que[t];
		size[u] = 1;
		int sing = 0;
		for (int i = fst[u]; i; i = edge[i].nex) {
			int v = edge[i].v;
			if (done[v]) continue;
			if (fa[u] == v) continue;
			size[u] += size[v];
			sing = max(sing, size[v]);
		}
		sing = max(sing, R - size[u]);
		tmp[u] = sing;
		if (sing < Sing) {
			Sing = sing;
		}
	}

	vector<int> ans; ans.clear();
	for (int i = 1; i <= R; i++)
		if (tmp[que[i]] == Sing) ans.push_back(que[i]);

	return ans;
}

void link_it(int base, int cent) {
	du[base]--;
	int L = 0, R = 0; que[++R] = base;
	fa[base] = 0;
	while (L < R) {
		int u = que[++L];
		for (int i = fst[u]; i; i = edge[i].nex) {
			int v = edge[i].v;
			if (done[v]) continue;
			if (fa[u] == v) continue;
			fa[v] = u;
			que[++R] = v;
		}
	}
	while (!sta.empty()) sta.pop();
	for (int i = 1; i <= R; i++) {
		int u = que[i];
		if (du[u] == 1) sta.push(u);
	}
	if (sta.empty())
		return;
	ans[++top] = (ANS) { cent, base, sta.top() };
	vec[cent].push_back(sta.top());
	while (!sta.empty()) {
		int u = sta.top(); sta.pop();
		du[u]--;
		for (int i = fst[u]; i; i = edge[i].nex) {
			int v = edge[i].v;
			if (done[v] || !du[v]) continue;
			if ((--du[v]) != 1) {
				ans[++top] = (ANS) { u, v, sta.top() };
				nex[u] = sta.top();
			}
			else {
				if (du[v]) sta.push(v);
				nex[u] = v;
			}
		}
	}
}

void proc(int f, int u) {
	int tp = 0;
	que[++tp] = f;
	for (; u; u = nex[u])
		que[++tp] = u;
	for (int i = tp - 3; i >= 1; i--)
		ans[++top] = (ANS) { que[i], que[i + 1], que[tp - 1] };
}

void solve() {
	vector <int> cent = bfs(1);
	for (int i : cent) done[i] = 1;
	for (int u : cent) {
		for (int i = fst[u]; i; i = edge[i].nex) {
			int v = edge[i].v;
			if (!done[v]) link_it(v, u);
		}
	}
	for (int u : cent) {
		for (int v : vec[u]) proc(u, v);
	}
}

int main() {
	scanf("%d",&n);
	for (int i = 1; i < n; i++) {
		int a, b;
		scanf("%d %d",&a,&b);
		make_edge(a, b);
	}

	solve();

	printf("%d\n", top);
	for (int i = 1; i <= top; i++)
		printf("%d %d %d\n",ans[i].a, ans[i].b, ans[i].c);
	return 0;
}

#include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream>

using namespace std;

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
#define TRACE(x) cout << #x << " = " << x << endl
#define _ << " _ " <<

typedef long long llint;

const int MAX = 200200;

vector<int> E[MAX];

int sz[MAX];
int bal[MAX];

void dfs(int x, int dad) {
  sz[x] = 1;
  bal[x] = 0;
  for (int y: E[x]) {
    if (y != dad) {
      dfs(y, x);
      sz[x] += sz[y];
      bal[x] = max(bal[x], sz[y]);
    }
  }
}

vector<pair<pair<int, int>, int>> ret;

vector<int> v;
int parent[MAX];

void explore(int x, int dad) {
  v.push_back(x);
  for (int y: E[x])
    if (y != dad) {
      parent[y] = x;
      explore(y, x);
    }
}

void solve(int x, int dad) {
  for (int y: E[x]) {
    if (y != dad) {
      v.clear();
      explore(y, x);

      int center = v[0];
      int cur_center = center;
      for (int i = (int)v.size()-1; i > 0; --i) {
        if (parent[v[i]] != center) {
          ret.push_back({{x, cur_center}, v[i]});
          ret.push_back({{v[i], parent[v[i]]}, center});
          cur_center = v[i];
        }
      }

      if (cur_center != center) {
        ret.push_back({{x, cur_center}, center});
      }
    }
  }
}

int main(void) {
  int n;
  scanf("%d", &n);
  REP(i, n-1) {
    int a, b;
    scanf("%d %d", &a, &b);
    --a, --b;
    E[a].push_back(b);
    E[b].push_back(a);
  }

  dfs(0, -1);
  vector<int> centroids;
  REP(x, n) {
    bal[x] = max(bal[x], n - sz[x]);
    if (bal[x] <= n/2) centroids.push_back(x);
  }

  if (centroids.size() == 1) {
    solve(centroids[0], -1);
  } else if (centroids.size() == 2) {
    solve(centroids[0], centroids[1]);
    solve(centroids[1], centroids[0]);
  } else assert(false);

  printf("%d\n", (int)ret.size());
  for (auto p: ret) printf("%d %d %d\n", p.first.first+1, p.first.second+1, p.second+1);
  return 0;
}

#include<bits/stdc++.h>
#define sqr(x) ((x)*(x))
#define ll long long
#define ull unsigned long long
#define ui unsigned int
#define ld long double
#define vi vector<int>
#define HEAP(...) priority_queue<__VA_ARGS__ >
#define heap(...) priority_queue<__VA_ARGS__,vector<__VA_ARGS__ >,greater<__VA_ARGS__ > >
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define debuge cerr<<"isok"<<endl
#define debug(x) cerr<<#x<<"="<<x<<endl
#define dprintf(...) fprintf(stderr,__VA_ARGS__)
#define SS second
#define FF first
#define ls (k<<1)
#define rs (k<<1|1)
#define clr(a,x) memset(a,x,sizeof(a))
#define cpy(a,x) memcpy(a,x,sizeof(a))
#define file(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
#define SZ(x) ((int)x.size())
using namespace std;
template<class T> inline void gmin(T &x,const T &y){if(x>y) x=y;}
template<class T> inline void gmax(T &x,const T &y){if(x<y) x=y;}
const int BufferSize=1<<16;
char buffer[BufferSize],*Bufferhead,*Buffertail;
bool Terminal;
inline char Getchar(){
	if(Bufferhead==Buffertail){
		int l=fread(buffer,1,BufferSize,stdin);
		if(!l){Terminal=1;return 0;}
		Buffertail=(Bufferhead=buffer)+l;
	}
	return *Bufferhead++;
}
template<class T>inline bool read(T &x){
	x=0;char c=Getchar(),rev=0;
	while(c<'0'||c>'9'){c=Getchar();rev|=c=='-';if(Terminal)return 0;}
	while(c>='0'&&c<='9') x=x*10+c-'0',c=Getchar();
	if(c=='.'){
		c=Getchar();double t=0.1;
		while(c>='0'&&c<='9') x=x+(c-'0')*t,c=Getchar(),t=t/10;
	}
	x=rev?-x:x;
	return 1;
}
template<class T1,class T2> inline bool read(T1 &x,T2 &y){return read(x)&read(y);}
template<class T1,class T2,class T3> inline bool read(T1 &x,T2 &y,T3 &z){return read(x)&read(y)&read(z);}
template<class T1,class T2,class T3,class T4> inline bool read(T1 &x,T2 &y,T3 &z,T4 &w){return read(x)&read(y)&read(z)&read(w);}
inline bool reads(char *x){
	char c=Getchar();
	while(c<33||c>126){c=Getchar();if(Terminal)return 0;}
	while(c>=33&&c<=126) (*x++)=c,c=Getchar();
	*x=0;return 1;
}
template<class T>inline void print(T x,const char c='\n'){
	if(!x){putchar('0');putchar(c);return;}
	if(x<0) putchar('-'),x=-x;
	int m=0,a[20];
	while(x) a[m++]=x%10,x/=10;
	while(m--) putchar(a[m]+'0');
	putchar(c);
}
//--------------------------------head---------------------------------------------

const int inf=0x3f3f3f3f;
const int N=200005,M=100005,mod=1e9+7;
template<class T,class S> inline void ch(T &x,const S y){x=(x+y)%mod;}
inline int exp(int x,int y,const int mod=::mod){
	int ans=1;
	while(y){
		if(y&1) ans=(ll)ans*x%mod;
		x=(ll)x*x%mod;y>>=1;
	}return ans;
}

struct node{int x,y,ty;};
int n,rt,srt,last;
vi g[N],id;
vector<node> ans;
bool vis[N];

int findroot(int x,int f=-1){
	int tmp=0,res=1;
	for(int y:g[x]){
		if(y==f) continue;
		int t=findroot(y,x);
		res+=t;
		gmax(tmp,t);
	}
	gmax(tmp,n-res);
	if(tmp<=n/2) id.pb(x);
	return res;
}
void push(int x,int y,int ty){
	if(x==y||y==ty||x==ty) return;
	ans.pb((node){x,y,ty});
}
void dfs(int x,int f){
	vis[x]=1;
	push(rt,last,x);
	push(x,f,srt);last=x;
	for(int y:g[x])
		if(!vis[y]) dfs(y,x);
}

int main(){
#ifdef rqgao2014
	freopen("input.txt","r",stdin);
#endif
	read(n);
	for(int i=1;i<n;i++){
		int x,y;read(x,y);
		g[x].pb(y);g[y].pb(x);
	}
	findroot(1);
	for(int i:id) vis[i]=1;
	for(int i:id){
		rt=i;
		for(int x:g[i])
			if(!vis[x]){
				srt=last=x;
				dfs(x,i);
				push(rt,last,srt);
			}
	}
	printf("%d\n",SZ(ans));
	for(node i:ans) printf("%d %d %d\n",i.x,i.y,i.ty);
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

int n, croot, ccent, centc;
vector<vector<int>> g(200001), ans;
vector<int> w(200001, 1), par(200001), ct, now(3);

void dfs(int v, int p) {
	int s = n - 1, cc = 1;
	for (int u : g[v]) {
		if (u == p)
			continue;
		dfs(u, v);
		if (w[u] > n / 2)
			cc = 0;
		s -= w[u];
		w[v] += w[u];
	}
	if (cc && s <= n / 2)
		ct.push_back(v);
}

void dfs2(int v, int p) {
	now[0] = ccent;
	now[1] = centc;
	now[2] = v;
	ans.push_back(now);
	centc = v;
	now[0] = v;
	now[1] = p;
	now[2] = croot;
	ans.push_back(now);
	for (int u : g[v]) {
		if (u == p)
			continue;
		dfs2(u, v);
	}
}

int main() {
	cin >> n;
	for (int i = 1; i < n; i++) {
		int u, v;
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1, -1);
	if (ct.size() == 2) {
		g[ct[0]].erase(find(g[ct[0]].begin(), g[ct[0]].end(), ct[1]));
		g[ct[1]].erase(find(g[ct[1]].begin(), g[ct[1]].end(), ct[0]));
	}
	for (int v : ct) {
		ccent = v;
		for (int u : g[v]) {
			croot = u;
			centc = u;
			for (int w : g[croot]) {
				if (w == ccent)
					continue;
				dfs2(w, croot);
			}
			now[0] = ccent;
			now[1] = centc;
			now[2] = croot;
			ans.push_back(now);
		}
	}
	cout << ans.size() << '\n';
	for (auto vv : ans)
		cout << vv[0] << ' ' << vv[1] << ' ' << vv[2] << '\n';
}

#include <bits/stdc++.h>

#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()

using namespace std;

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

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }

template<typename T> T inf;
template<> constexpr int inf<int> = 1e9;
template<> constexpr ll inf<ll> = 1e18;
template<> constexpr ld inf<ld> = 1e30;

struct yes_no : numpunct<char> {
  string_type do_truename()  const { return "Yes"; }
  string_type do_falsename() const { return "No"; }
};

set<int> g[201000];
bool visited[201000];
int cnt[201000];

int dfs1(int v) {
  visited[v] = true;
  int res = 1;
  for (int i: g[v]) {
    if (visited[i]) continue;
    res += dfs1(i);
  }
  return cnt[v] = res;
}

int dfs2(int v, int n) {
  visited[v] = true;
  for (int i: g[v]) {
    if (visited[i]) continue;
    if (cnt[i] * 2 > n) return dfs2(i, n);
  }
  return v;
}

vector<tuple<int,int,int>> res;

pair<int,int> dfs3(int p, int v) {
  visited[v] = true;
  vector<int> ls;
  vector<int> is;
  for (int i: g[v]) {
    if (visited[i]) continue;
    auto ret = dfs3(v, i);
    is.push_back(ret.first);
    ls.push_back(ret.second);
  }
  if (is.empty()) return make_pair(v, v);
  res.emplace_back(p, v, ls[0]);
  REP(i,is.size() - 1) res.emplace_back(is[i], v, ls[i + 1]);
  // cout << "func " << p << " " << v << " " << ls[0] << " " << is.back() << endl;
  return make_pair(ls[0], v);
}

void dfs_master(int v, int n) {
  visited[v] = true;
  for (int i: g[v]) {
    if (visited[i]) continue;
    // cout << "cnt " << i << " " << cnt[i] << " " << n << endl;
    if (cnt[i] * 2 >= n) dfs_master(i, n);
    else {
      // cout << "dfs3 " << v << " " << i << endl;
      dfs3(v, i);
    }
  }
}

int dfs4(int v) {
  visited[v] = true;
  int cand = v;
  for (int i: g[v]) {
    if (visited[i]) continue;
    cand = dfs4(i);
    res.emplace_back(v, i, cand);
  }
  return cand;
}

void dfs_master2(int v, int n) {
  visited[v] = true;
  for (int i: g[v]) {
    if (visited[i]) continue;
    if (cnt[i] * 2 >= n) dfs_master2(i, n);
    else {
      int cand = dfs4(i);
      res.emplace_back(v, i, cand);
    }
  }
}

int main() {
  locale loc(locale(), new yes_no);
  cout << boolalpha;
  cout.imbue(loc);
  int n;
  scanf("%d", &n);
  REP(i,n-1) {
    int s, t;
    scanf("%d%d", &s, &t);
    --s; --t;
    g[s].insert(t);
    g[t].insert(s);
  }
  memset(visited, 0, sizeof(visited));
  dfs1(0);
  memset(visited, 0, sizeof(visited));
  const int root = dfs2(0, n);
  memset(visited, 0, sizeof(visited));
  dfs1(root);
  // REP(i,n) cout << cnt[i] << " "; cout << endl;

  memset(visited, 0, sizeof(visited));
  dfs_master(root, n);
  for (auto t: res) {
    int x, y, z;
    tie(x, y, z) = t;
    g[x].erase(y);
    g[y].erase(x);
    g[x].insert(z);
    g[z].insert(x);
  }

  memset(visited, 0, sizeof(visited));
  dfs1(root);
  memset(visited, 0, sizeof(visited));
  dfs_master2(root, n);

  cout << res.size() << endl;
  for (auto t: res) {
    int x, y, z;
    tie(x, y, z) = t;
    cout << x + 1 << " " << y + 1 << " " << z + 1 << endl;
  }
  return 0;
}

#include <cstdio>
using namespace std;
struct node
{
	int to;
	node *next;
};
struct rec
{
	int a,b,c;
};
int cen1,cen2,i,j,m,n,cen,cnt,cntans;
int size[200005],ver[200005],ind[200005],now[200005],dep[200005];
node *nd[200005];
rec ans[400005];
bool centroid[200005];
void addd(int u,int v){
	node *p=new node();
	p->to=v;
	p->next=nd[u];
	nd[u]=p;
}
void dfs0(int u,int pre){
	node *p;
	p=nd[u];
	while(p){
		if ((p->to!=pre)&&(p->to!=cen1)&&(p->to!=cen2)) {
			dep[p->to]=dep[u]+1;
			dfs0(p->to,u);
		}
		p=p->next;
	}
}
void dfs2(int u,int pre){
	node *p;
	node *pp;
	p=nd[u];
	if ((u!=cen)&&(u!=ver[cnt])){
		ind[u]=cnt;
		cntans++;
		ans[cntans].a=cen;
		ans[cntans].b=now[cnt];
		ans[cntans].c=u;
		now[cnt]=u;
		pp=nd[u];
		while(pp){
			if (pp->to!=cen) {
				if (dep[u]>dep[pp->to]){
					cntans++;
					ans[cntans].a=u;
					ans[cntans].b=pp->to;
					ans[cntans].c=ver[cnt];
				}
			}
			pp=pp->next;
		}
	}
	while(p){
		if ((p->to!=pre)&&(p->to!=cen1)&&(p->to!=cen2)) {
			if (u==cen){
				cnt++;
				ver[cnt]=p->to;
				now[cnt]=p->to;
			}
			//dep[p->to]=dep[u]+1;
			dfs2(p->to,u);

		}
		p=p->next;
	}
}
void dfs(int u,int pre){
	node *p;
	p=nd[u];
	size[u]=1;
	while(p){
		if (p->to!=pre) {
			dfs(p->to,u);
			size[u]+=size[p->to];
			if (size[p->to]*2>n) centroid[u]=false;
		}
		p=p->next;
	}
	if (2*(n-size[u])>n) centroid[u]=false;
	//if (centroid[u]) cen=u;
}
int main(){
	cnt=cntans=0;
	scanf("%d",&n);
	int x,y;
	for(i=1;i<=n-1;i++){
		scanf("%d%d",&x,&y);
		addd(x,y);
		addd(y,x);
	}
	for(i=1;i<=n;i++) centroid[i]=true;
	dfs(1,-1);
	//dep[cen]=0;
	for(i=1;i<=n;i++){
		if (centroid[i]){
			if (cen1==0) cen1=i;else cen2=i;
		}
	}
	cen=cen1;
	dfs0(cen,-1);
	dfs2(cen,-1);
	for(i=1;i<=cnt;i++){
		cntans++;
		ans[cntans].a=cen;
		ans[cntans].b=now[i];
		ans[cntans].c=ver[i];
	}
	cnt=0;
	cen=cen2;
	dfs0(cen,-1);
	dfs2(cen,-1);
	for(i=1;i<=cnt;i++){
		cntans++;
		ans[cntans].a=cen;
		ans[cntans].b=now[i];
		ans[cntans].c=ver[i];
	}
	//printf("%d\n", );
	printf("%d\n",cntans);
	for(i=1;i<=cntans;i++){
		printf("%d %d %d\n",ans[i].a,ans[i].b,ans[i].c);
	}
	return 0;
}

/* "In the name of Allah" */
#include <bits/stdc++.h>
using namespace std;

const int N = 2 * 100 * 1000 + 2;
int n, cnt[N], mx[N], par[N], x, y = -1;
vector <int> adj[N], vec, ans[3];

void dfs1(int u, int p) {
	cnt[u] = 1;
	for (int v: adj[u])
		if (v != p) {
			dfs1(v, u);
			cnt[u] += cnt[v];
			if (mx[u] == -1 || cnt[mx[u]] < cnt[v])
				mx[u] = v;
		}
}

void findCentroid() {
	memset(mx, -1, sizeof mx);
	dfs1(0, -1);
	while (mx[x] != -1 && cnt[mx[x]] * 2 > n)
		x = mx[x];
	if (cnt[mx[x]] * 2 == n)
		y = mx[x];
}

void dfs2(int u, int p) {
	for (int v: adj[u])
		if (v != p) {
			vec.push_back(v);
			par[v] = u;
			dfs2(v, u);
		}
}

void add(int a, int b, int c) {
	ans[0].push_back(a + 1);
	ans[1].push_back(b + 1);
	ans[2].push_back(c + 1);
}

void solve(int root) {
	if (root != -1)
		for (int i = 0; i < adj[root].size(); i++) {
			int u = adj[root][i];
			if (u != x && u != y) {
				vec.clear();
				dfs2(u, root);
				for (int v: vec) {
					add(root, u, v);
					add(v, par[v], adj[root][i]);
					u = v;
				}
				add(root, u, adj[root][i]);
			}
		}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 1, u, v; i < n; i++) {
		cin >> u >> v;
		adj[--u].push_back(--v);
		adj[v].push_back(u);
	}
	findCentroid();
	solve(x), solve(y);
	cout << ans[0].size() << endl;
	for (int i = 0; i < ans[0].size(); i++)
		cout << ans[0][i] << ' ' << ans[1][i] << ' ' << ans[2][i] << endl;
}

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

namespace debug{
    void __(short x){cout<<x;}
    void __(int x){cout<<x;}
    void __(long long x){cout<<x;}
    void __(unsigned long long x){cout<<x;}
    void __(double x){cout<<x;}
    void __(long double x){cout<<x;}
    void __(char x){cout<<x;}
    void __(const char*x){cout<<x;}
    void __(const string&x){cout<<x;}
    void __(bool x){cout<<(x?"true":"false");}
    template<class P1,class P2>
    void __(const pair<P1,P2>&x){__("("),__(x.first),__(", "),__(x.second),__(")");}
    template<class T>
    void __(const vector<T>&x){__("{");bool _ffs=0;for(const auto&v:x)__(_ffs?", ":""),__(v),_ffs=1;__("}");}
    void screm(){__("\n");}
    template<class T1,class... T2>
    void screm(const T1&t1,const T2&...t2){__(t1);if(sizeof...(t2))__(" | "),screm(t2...);else __("\n");}
    void pr(){__("\n");}
    template<class T1,class... T2>
    void pr(const T1&t1,const T2&...t2){__(t1);if(sizeof...(t2))__(" "),pr(t2...);else __("\n");}
}

using namespace debug;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef pair<ld,ld> pld;
typedef vector<int> vi;
typedef vector<ll> vl;

#define pb push_back

const int MN = 2e5+5;
int N, i, x, y, sz[MN], mx[MN], cc[MN], par[MN];
vi adj[MN], c; pii e;
struct op{int a, b, c;};
vector<op> ans;

int dfs1(int n,int p){
    sz[n] = 1;
    for(auto v : adj[n]){
        if(v==p) continue;
        int ss = dfs1(v, n);
        sz[n] += ss;
        mx[n] = max(mx[n], ss);
    }
    return sz[n];
}

void dfs2(int n,int p){
    if(2*mx[n]<=N&&2*(N-sz[n])<=N) cc[n]=1, c.pb(n);
    for(auto v : adj[n]){
        if(v==p) continue;
        dfs2(v, n);
    }
}

void solve(int n,int p,int r){
    if(p!=r){
        ans.pb({e.first,e.second,n});
        e.second = n;
        ans.pb({n,p,r});
    }
    for(auto v : adj[n]) if(v!=p) solve(v,n,r);
}

int main(){
    for(scanf("%d",&N),i=1;i<N;i++){
        scanf("%d%d",&x,&y);
        adj[x].pb(y);
        adj[y].pb(x);
    }
    dfs1(1,0);
    dfs2(1,0);
    for(auto cent : c){
        for(auto rt : adj[cent]){
            if(cc[rt]) continue;
            e = {cent, rt};
            for(auto v : adj[rt]) if(v!=cent) solve(v,rt,rt);
            ans.pb({e.first,e.second,rt});
        }
    }
    printf("%d\n",ans.size());
    for(auto v : ans) printf("%d %d %d\n",v.a,v.b,v.c);
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define e1 first
#define e2 second
#define pb push_back
#define mp make_pair
#define boost ios_base::sync_with_stdio(false)
#define eb emplace_back
#define OUT(x) {cout << x; exit(0); }
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define scanf(...) scanf(__VA_ARGS__)?:0
typedef long long int ll;
typedef unsigned long long ull;
typedef pair <int, int> PII;
typedef pair <ll, ll> PLL;
typedef pair <PLL, int> PLLI;
typedef pair <PLL, PLL> PP;
typedef pair <PII, int> PPI;
typedef pair <ll, int> PLI;
typedef unsigned int ui;
const int mod = 1000000;
const int inf = 1e9+9;
const ll MOD = 1e9+696969;
const long long INF = 1e18+3;
const int maxn = 500100;
vector <int> v[maxn];
vector <int> centroids;
vector <PPI> wynik;
int n;
int r[maxn], maks[maxn];
bool centroid[maxn];

void przelacz(int root, int skad, int dokad) {
	wynik.pb(mp(mp(root, skad), dokad));
}

void dfs(int x, int p) {
	r[x] = 1;
	for (auto u : v[x])
		if (u != p) {
			dfs(u, x);
			r[x] += r[u];
			maks[x] = max(maks[x], r[u]);
		}
}
vector <int> met;
int d[maxn], ojciec[maxn];

void find(int x, int par) {
	met.pb(x);
	ojciec[x] = par;
	for (auto u : v[x])
		if (u != par) {
			d[u] = d[x] + 1;
			find(u, x);
		}
}

int LAST;
void fuckRightInTheCentroid(int x, int veryBig) {
	met.clear();
	d[x] = 0;
	find(x, veryBig);
	LAST = x;
	for (auto u : met)
		if (d[u] > 1)
		{
			przelacz(veryBig, LAST, u);
			przelacz(u, ojciec[u], x);
			LAST = u;
		}

	if (LAST != x) przelacz(veryBig, LAST, x);
}

void fuckTree(int x) {
	for (auto u : v[x])
		if (!centroid[u]) fuckRightInTheCentroid(u, x);
}

int main()
{
	boost;
	cin >> n;
	FOR(i, 2, n) {
		int a, b;
		cin >> a >> b;
		v[a].pb(b);
		v[b].pb(a);
	}

	int pol = (n / 2);
	dfs(1, 1);
	FOR(i, 1, n)
	{
		maks[i] = max(maks[i], n - r[i]);
		if (maks[i] <= pol) centroids.pb(i);
	}

	for (auto u : centroids) centroid[u] = 1;

	for (auto u : centroids) fuckTree(u);

	cout << (int)wynik.size() << "\n";
	for (auto u : wynik) cout << u.e1.e1 << ' ' << u.e1.e2 << ' ' << u.e2 << "\n";
}

#pragma comment(linker, "/STACK:250000000")
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <ctime>
#include <cassert>
#include <memory.h>
#include <fstream>
#include <bitset>
#include <algorithm>
#include <cmath>

//#include <unordered_map>

#define forn(i, n) for (int i = 0; i < int(n); i++)
#define for1(i, n) for (int i = 1; i < int(n); i++)
#define nfor(i, n) for (int i = int(n) - 1; i >= 0; i--)
#define forr(i, n) for (int i = int(n) - 1; i >= 0; i--)
#define fore(i, l, r) for (int i = int(l); i < int(r); i++)
#define forft(i, l, r) for (int i = int(l); i < int(r); i++)
#define correct(x, y, n, m) (0 <= (x) && (x) < (n) && 0 <= (y) && (y) < (m))
#define all(a) (a).begin(), (a).end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define mp(x, y) make_pair((x), (y))
#define ms(a, v) memset(a, v, sizeof(a))
#define x first
#define y second
#define X first
#define Y second
#define ft first
#define sc second

using namespace std;

typedef long long li;
typedef long double ld;
typedef pair<int, int> pt;

template<typename X> inline X abs(const X& a) { return a < 0? -a: a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

const int INF = int(1e9);
const li INF64 = li(4e18);
const ld EPS = 1e-9, PI = 3.1415926535897932384626433832795;

const int N = 2e5 + 10;

int n;
vector<int> g[N];
int d[N];
vector<pair<int, pt> > ans;

bool read() {
	scanf("%d", &n);

	forn(i, n - 1) {
		int x, y;
		scanf("%d%d", &x, &y);
		--x, --y;
		g[x].pb(y);
		g[y].pb(x);
	}

	return true;
}

void calcd(int v, int p = -1) {
	d[v] = 1;

	forn(i, sz(g[v])) {
		int u = g[v][i];
		if (u != p) {
			calcd(u, v);
			d[v] += d[u];
		}
	}
}

pt getc(int v, int p = -1) {
	forn(i, sz(g[v])) {
		int u = g[v][i];

		if (u == p) {
			continue;
		}

		if (d[u] == n - d[u]) {
			return mp(v, u);
		}

		if (d[u] * 2 > n) {
			return getc(u, v);
		}
	}

	return mp(v, -1);
}

pt findc() {
	calcd(0);
	return getc(0);
}

void dfs(int v, int p, pt &cur, int t) {
	if (p != cur.X && p != t) {
		ans.pb(mp(cur.X, mp(cur.Y, v)));
		ans.pb(mp(v, mp(p, t)));
		cur.Y = v;
	}

	forn(i, sz(g[v])) {
		int u = g[v][i];

		if (u != p) {
			dfs(u, v, cur, t);
		}
	}
}

void solve() {
	pt c = findc();

	forn(i, sz(g[c.X])) {
		int u = g[c.X][i];

		if (u == c.Y) {
			continue;
		}

		pt cur = mp(c.X, u);
		dfs(u, c.X, cur, u);

		if (cur.Y != u) {
			ans.pb(mp(cur.X, mp(cur.Y, u)));
		}
	}

	if (c.Y != -1) {
		forn(i, sz(g[c.Y])) {
			int u = g[c.Y][i];

			if (u == c.X) {
				continue;
			}

			pt cur = mp(c.Y, u);
			dfs(u, c.Y, cur, u);

			if (cur.Y != u) {
				ans.pb(mp(cur.X, mp(cur.Y, u)));
			}
		}
	}

	printf("%d\n", sz(ans));

	forn(i, sz(ans)) {
		printf("%d %d %d\n", ans[i].X + 1, ans[i].Y.X + 1, ans[i].Y.Y + 1);
	}
}

int main() {
#ifdef AR
	assert(freopen("input.txt", "rt", stdin));
	assert(freopen("output.txt", "wt", stdout));
#endif

	srand(time(NULL));

	cout << setprecision(10) << fixed;
	cerr << setprecision(10) << fixed;

	read();
	solve();

#ifdef AR
	cerr << "Time: " << clock() << endl;
#endif
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int n , pre[N] , mcnt;
struct edge {
    int x , next;
} e[N << 1];

int s[N];
bool f[N];

vector< tuple<int , int , int> > res;

int root[N] , rootCnt , maxSize;

set< pair<int , int> > E;

pair<int , int> Find(int x , int fa , int cnt) {
    s[x] = 1; int m = 0;
    for (int i = pre[x] ; ~i ; i = e[i].next)
        if (!f[e[i].x] && e[i].x != fa) {
            Find(e[i].x , x , cnt);
            m = max(s[e[i].x] , m);
            s[x] += s[e[i].x];
        }
    m = max(m , cnt - s[x]);
    if (m < maxSize) {
        maxSize = m;
        rootCnt = 0;
    }
    if (m == maxSize) {
        root[rootCnt ++] = x;
    }
}

int getSize(int x , int fa) {
    int size = 1;
    for (int i = pre[x] ; ~i ; i = e[i].next) {
        int y = e[i].x;
        if (!f[y] && y != fa) {
            size += getSize(y , x);
        }
    }
    return size;
}

void update(int x , int y , int w) {
    if (x > y) swap(x , y);
    if (w > 0) {
        E.insert({x , y});
    } else {
        E.erase({x , y});
    }
}

pair<int , int> gao(int x , int fa) {
    int cur = fa;
    int beg = 0;
    int child = 0;
    for (int i = pre[x] ; ~i ; i = e[i].next) {
        int y = e[i].x;
        if (!f[y] && y != fa) {
            ++ child;
            int w , z;
            tie(w , z) = gao(y , x);
            if (cur == fa) {
                beg = z;
            }
            res.emplace_back(cur , x , z);
            update(cur , x , -1);
            update(cur , z , 1);
            cur = w;
        }
    }
    if (!child) {
        return {x , x};
    } else {
        return {beg , x};
    }
}
int leaf;
int boom(int x , int fa , vector<int> &v) {
    v.push_back(x);
    int child = 0;
    for (int i = pre[x] ; ~i ; i = e[i].next) {
        int y = e[i].x;
        if (!f[y] && y != fa) {
            child ++;
            boom(y , x , v);
        }
    }
    //assert(child == 0 || child == 1);
}

int divide(int x , int cnt) {
    rootCnt = 0;
    maxSize = 1 << 30;
    Find(x , 0 , cnt);
    vector<int> p;
    for (int i = 0 ; i < rootCnt ; ++ i) {
        int x = root[i];
        f[x] = 1;
        p.emplace_back(x);
    } //cout << endl;
    //cout << p.size() << endl;
    //assert(p.size() == 1 || p.size() == 2);
    int R = p.back();
    for (auto &x : p) {
        for (int i = pre[x] ; ~i ; i = e[i].next) {
            int y = e[i].x;
            if (!f[y]) {
                gao(y , x);
            }
        }
    }

    memset(pre , -1 ,sizeof(pre)); mcnt = 0;
    for (auto &it : E) {
        int x = it.first , y = it.second;
        e[mcnt] = (edge) {y , pre[x]} , pre[x] = mcnt ++;
        e[mcnt] = (edge) {x , pre[y]} , pre[y] = mcnt ++;
    }

    for (auto &x : p) {
        for (int i = pre[x] ; ~i ; i = e[i].next) {
            int y = e[i].x;
            if (!f[y]) {
                vector<int> route;
                route.push_back(x);
                boom(y , x , route);
                for (int j = route.size() - 2 ; j >= 0 ; -- j) {
                    res.emplace_back(route[j] , route[j + 1] , route.back());
                }
            }
        }
    }

}

int main() {
    scanf("%d" , &n);
    memset(pre , -1 , sizeof(pre));
    for (int i = 1 ; i < n ; ++ i) {
        int x , y;
        scanf("%d%d" , &x , &y);
        if (x > y) swap(x , y);
        E.insert({x , y});
        e[mcnt] = (edge) {y , pre[x]} , pre[x] = mcnt ++;
        e[mcnt] = (edge) {x , pre[y]} , pre[y] = mcnt ++;
    }
    divide(1 , n);
    printf("%d\n" , res.size());
    for (auto it : res) {
        printf("%d %d %d\n" , get<0>(it) , get<1>(it) , get<2>(it));
    }
}

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<int> outgo[202020];
int n;
int size[202020];
vector<int> root;
void search(int now,int fa)
{
	size[now]=1;
	int mx=-1;
	for(int i=0;i<outgo[now].size();i++)
	{
		int to=outgo[now][i];
		if(to==fa)
			continue;
		search(to,now);
		size[now]+=size[to];
		mx=max(mx,size[to]);
	}
	mx=max(mx,n-size[now]);
	if(mx<=n/2)
		root.push_back(now);
}
int rt;
int first,last;
vector<pair<int,pair<int,int> > > ans;
void search2(int now,int fa)
{
	if(fa!=rt)
	{
		ans.push_back(make_pair(rt,make_pair(last,now)));
		ans.push_back(make_pair(now,make_pair(fa,first)));
		last=now;
	}
	for(int i=0;i<outgo[now].size();i++)
	{
		int to=outgo[now][i];
		if(to==fa)
			continue;
		search2(to,now);
	}
}
void solve(int now,int fa)
{
	rt=now;
	for(int i=0;i<outgo[now].size();i++)
	{
		int to=outgo[now][i];
		if(to==fa)
			continue;
		first=last=to;
		search2(to,now);
		ans.push_back(make_pair(now,make_pair(last,first)));
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		outgo[a].push_back(b);
		outgo[b].push_back(a);
	}
	search(1,0);
	if(root.size()==1)
		solve(root[0],0);
	else
	{
		solve(root[0],root[1]);
		solve(root[1],root[0]);
	}
	printf("%lu\n",ans.size());
	for(int i=0;i<ans.size();i++)
		printf("%d %d %d\n",ans[i].first,ans[i].second.first,ans[i].second.second);
	return 0;
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
using namespace std;

#ifdef LOCAL
	#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
	#define eprintf(...) 42
#endif

typedef long long ll;
typedef pair<int, int> pii;
#define mp make_pair

const int N = 200200;
int n;
vector<int> g[N];
int deg[N];
int sz[N];
int ans[2 * N][3];
int ansSz;
bool bad[N];
int a[N];
int m;
set<pii> setik;

void addAns(int v, int u, int w)
{
	ans[ansSz][0] = v + 1;
	ans[ansSz][1] = u + 1;
	ans[ansSz][2] = w + 1;
	ansSz++;
}

void dfs(int v)
{
	sz[v] = 1;
	for (int u : g[v]) {
		if (sz[u]) continue;
		dfs(u);
		sz[v] += sz[u];
	}
}

vector<int> findCentr(int v)
{
	vector<int> res;
	while(true) {
		int w = -1;
		for (int u : g[v]) {
			if (sz[u] > sz[v]) continue;
			if (2 * sz[u] >= n) {
				w = u;
				break;
			}
		}
		if (w == -1) {
			res.push_back(v);
			return res;
		}
		if (2 * sz[w] == n) {
			res.push_back(v);
			res.push_back(w);
			return res;
		}
		v = w;
	}
}

void dfs2(int v)
{
	for (int u : g[v]) {
		if (bad[u]) continue;
		if (deg[u]) continue;
		deg[v]++;
		deg[u]++;
		dfs2(u);
	}
	setik.insert(mp(deg[v], v));
}

void solve(int V, int lst)
{
	setik.clear();
	dfs2(V);
	m = 0;
	a[m++] = lst;
	while((int)setik.size() > 1) {
		int v = setik.begin()->second;
		setik.erase(setik.begin());
		if (deg[v] != 1) throw;
		a[m++] = v;
		bad[v] = 1;
		addAns(lst, V, v);
		for (int u : g[v]) {
			if (bad[u]) continue;
			setik.erase(mp(deg[u], u));
			deg[u]--;
			setik.insert(mp(deg[u], u));
			V = u;
		}
		lst = v;
	}
	m--;
	lst = a[m];
	for (int i = m - 1; i >= 0; i--)
		addAns(a[i], a[i + 1], lst);
}

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

	scanf("%d", &n);
	for (int i = 1; i < n; i++) {
		int v, u;
		scanf("%d%d", &v, &u);
		v--;u--;
		g[v].push_back(u);
		g[u].push_back(v);
	}
	dfs(0);
	vector<int> V = findCentr(0);
	for (int v : V)
		bad[v] = 1;

	for (int v : V) {
		for (int u : g[v]) {
			if (bad[u]) continue;
			solve(u, v);
		}
	}

	printf("%d\n", ansSz);
	for (int i = 0; i < ansSz; i++)
		printf("%d %d %d\n", ans[i][0], ans[i][1], ans[i][2]);

	return 0;
}

#include <cstdio>
#include <algorithm>
#include <vector>
#include <array>

using namespace std;

typedef long long ll;

const int N = 200200;

int n;
vector<int> g[N], c;
int sz[N];
vector<array<int, 3>> a;
vector<pair<int, int>> d;
bool u[N];

void go(int v)
{
    sz[v] = 1;
    int m = 0;
    for (int to : g[v])
        if (sz[to] == 0)
        {
            go(to);
            sz[v] += sz[to];
            m = max(m, sz[to]);
        }
    m = max(m, n - sz[v]);
    if (m * 2 <= n) c.push_back(v);
}

void og(int v, int c, int par = -1)
{
    for (int to : g[v])
        if (!u[to] && to != par)
            og(to, c, v);
    if (par != -1 && par != c)
        d.emplace_back(v, par);
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i < n; ++i)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        --x; --y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    go(0);
    for (int center : c) u[center] = true;
    for (int center : c)
    {
        for (int v : g[center])
        {
            if (u[v]) continue;
            d.clear();
            og(v, v);
            if (d.size() == 0) continue;
            for (size_t i = 0; i < d.size(); ++i)
                if (d[i].second != -1 && d[i].second != v)
                {
                    a.push_back({{center, i == 0 ? v : d[i - 1].first, d[i].first}});
                    a.push_back({{d[i].first, d[i].second, v}});
                }
            a.push_back({{center, d.back().first, v}});
        }
    }
    printf("%d\n", (int)a.size());
    for (auto& x : a)
        printf("%d %d %d\n", x[0] + 1, x[1] + 1, x[2] + 1);

    return 0;
}

#include <bits/stdc++.h>
#include <random>

using ll = long long;
using ld = long double;
using namespace std;

const int MAXN = 300001;

vector <int> e[MAXN];

int n;

int par[MAXN];

int sz[MAXN];

void dfs1(int v, int p) {
    par[v] = p;
    sz[v] = 1;
    for (int u : e[v]) {
        if (u != p) {
            dfs1(u, v);
            sz[v] += sz[u];
        }
    }
}

vector <int> cl;

void dfs3(int v, int p) {
    par[v] = p;
    for (int u : e[v]) {
        if (u != p) {
            dfs3(u, v);
        }
    }
    cl.push_back(v);
}

struct Val {
    int a, b, c;

    Val(int a, int b, int c)
        : a(a),
          b(b),
          c(c) {
    }
};

vector <Val> ans;

int sum = 0;

void ch(int a, int b, int c) {
    assert(++sum <= 2 * n);
    if (b == c) return;
    ans.emplace_back(a, b, c);
}

void dfs2(int v, int p) {
    for (int u : e[v]) {
        if (u == p) continue;
        cl.clear();
        cl.push_back(v);
        dfs3(u, v);
        ch(v, u, cl[1]);

        for (int i = 1; i + 1 < cl.size(); i++) {
            ch(cl[i], par[cl[i]], cl[i + 1]);
        }

        for (int i = int(cl.size()) - 2; i >= 0; i--) {
            ch(cl[i], cl[i + 1], cl.back());
        }
    }

}

int main() {
#ifdef PAUNSVOKNO
	freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
#endif
	ios_base::sync_with_stdio(false); cout.setf(ios::fixed); cout.precision(20);
    cin >> n;
    for (int i = 1; i < n; i++) {
        int a, b;
        cin >> a >> b;
        e[a].push_back(b);
        e[b].push_back(a);
    }

    if (n == 1) {
        cout << 0 << "\n";
    }

    dfs1(1, 1);

    int cv = 1;

    for (int i = 1; i <= n; i++) {
        if (sz[i] * 2 >= n && sz[i] < sz[cv]) cv = i;
    }

    if (sz[cv] * 2 == n) {
        dfs2(cv, par[cv]);
        dfs2(par[cv], cv);
    } else {
        dfs2(cv, cv);
    }

    cout << ans.size() << "\n";
    for (auto v : ans)
        cout << v.a << " " << v.b << " " << v.c << "\n";
}

#include <cstdio>
#include <vector>
#include <algorithm>
#include <stack>
#include <tuple>
#include <set>
#include <iterator>

#define for_each(name, left, right, step) for (int name = left; name < right; name += step)

using namespace std;

typedef pair<int, int> pii;

int operations_made = 0;

vector<int> get_centroids(vector<vector<int> >& node_idx___neigh_idxes) {
    int nodes_nr = node_idx___neigh_idxes.size();
    vector<vector<int> > node_idx___children(nodes_nr);
    vector<int> node_idx___is_visited(nodes_nr, 0);
    stack<int> dfs_stack;
    dfs_stack.push(0);
    node_idx___is_visited[0] = 1;
    while (!dfs_stack.empty()) {
        int curr_node_idx = dfs_stack.top();
        dfs_stack.pop();
        for (auto neigh_idx : node_idx___neigh_idxes[curr_node_idx]) {
            if (!node_idx___is_visited[neigh_idx]) {
                node_idx___is_visited[neigh_idx] = 1;
                node_idx___children[curr_node_idx].push_back(neigh_idx);
                dfs_stack.push(neigh_idx);
            }
        }
    }
    vector<int> node_idx___subnodes_nr(nodes_nr, 1);
    for (auto& is_visited: node_idx___is_visited) {
        is_visited = 0;
    }
    dfs_stack.push(0);
    node_idx___is_visited[0] = 1;
    while (!dfs_stack.empty()) {
        int curr_node_idx = dfs_stack.top();
        bool all_children_visited = true;
        for (auto child_idx : node_idx___children[curr_node_idx]) {
            if (!node_idx___is_visited[child_idx]) {
                node_idx___is_visited[child_idx] = 1;
                dfs_stack.push(child_idx);
                all_children_visited = false;
            }
        }
        if (all_children_visited) {
            for (auto child_idx : node_idx___children[curr_node_idx]) {
                node_idx___subnodes_nr[curr_node_idx] += node_idx___subnodes_nr[child_idx];
            }
            dfs_stack.pop();
        }
    }
    vector<int> centroids;
    for_each(node_idx, 0, nodes_nr, 1) {
        bool is_centroid = true;
        int parent_subnodes = nodes_nr - 1;
        for (auto child_idx: node_idx___children[node_idx]) {
            //cout << node_idx___subnodes_nr[child_idx] << " ";
            if (node_idx___subnodes_nr[child_idx] > nodes_nr / 2) {
                is_centroid = false;
                break;
            }
            parent_subnodes -= node_idx___subnodes_nr[child_idx];
        }
        //cout << parent_subnodes << endl;
        if (parent_subnodes > nodes_nr / 2) {
            is_centroid = false;
        }
        if (is_centroid) {
            centroids.push_back(node_idx);
        }
    }

    return centroids;
}

pii straighten_subtree(int stone_idx, int curr_root_idx, vector<set<int> >& node_idx___neigh_idxes) {
    // cout << "*" << stone_idx << " " << curr_root_idx << endl;
    int neigh_nr = node_idx___neigh_idxes[curr_root_idx].size();
    if (neigh_nr == 1) {
        // cout << "8returned" << endl;
        return make_pair(curr_root_idx, curr_root_idx);
    }
    vector<pii> rel_neigh_idx___root__hangler;
    // int i = 0;
    set<int> curr_neigh_idxes = node_idx___neigh_idxes[curr_root_idx];
    for (auto& neigh_idx: curr_neigh_idxes) {
        if (neigh_idx != stone_idx) {
            rel_neigh_idx___root__hangler.push_back(straighten_subtree(curr_root_idx, neigh_idx, node_idx___neigh_idxes));
            // cout << "***"<< rel_neigh_idx___root__hangler[i].first << " " << rel_neigh_idx___root__hangler[i].second << endl;
            // i++;
        }
    }
    int curr_parent_idx = stone_idx;
    int next_root_idx = (neigh_nr == 2 ? curr_root_idx : rel_neigh_idx___root__hangler[0].second);

    // replace stone_idx curr_root_idx connection
    if (next_root_idx != curr_root_idx) {
        node_idx___neigh_idxes[stone_idx].insert(rel_neigh_idx___root__hangler[0].second);
        auto it = node_idx___neigh_idxes[stone_idx].find(curr_root_idx);
        node_idx___neigh_idxes[stone_idx].erase(it);
        it = node_idx___neigh_idxes[curr_root_idx].find(stone_idx);
        node_idx___neigh_idxes[curr_root_idx].erase(it);
        node_idx___neigh_idxes[rel_neigh_idx___root__hangler[0].second].insert(stone_idx);
        curr_parent_idx = rel_neigh_idx___root__hangler[0].first;
        printf("%d %d %d\n", stone_idx + 1, curr_root_idx + 1, rel_neigh_idx___root__hangler[0].second + 1);
        operations_made++;
        // cout << "**" << operation[0] << " " << operation[1] << " " << operation[2] << endl;
    }
    neigh_nr = rel_neigh_idx___root__hangler.size();
    for_each(neigh_idx, 1, neigh_nr - 1, 1) {
        //create curr_parent_idx, rel_neigh_idx___root__hangler[neigh_idx].second
        printf("%d %d %d\n", curr_parent_idx + 1, curr_root_idx + 1, rel_neigh_idx___root__hangler[neigh_idx].second + 1);
        operations_made++;
        // cout << "**" << operation[0] << " " << operation[1] << " " << operation[2] << endl;
        node_idx___neigh_idxes[curr_parent_idx].insert(rel_neigh_idx___root__hangler[neigh_idx].second);
        node_idx___neigh_idxes[rel_neigh_idx___root__hangler[neigh_idx].second].insert(curr_parent_idx);
        //tear curr_root_idx neigh
        auto it = node_idx___neigh_idxes[curr_parent_idx].find(curr_root_idx);
        node_idx___neigh_idxes[curr_parent_idx].erase(it);
        it = node_idx___neigh_idxes[curr_root_idx].find(curr_parent_idx);
        node_idx___neigh_idxes[curr_root_idx].erase(it);
        curr_parent_idx = rel_neigh_idx___root__hangler[neigh_idx].first;
    }
    // cout << "8returned" << endl;
    return make_pair(next_root_idx, rel_neigh_idx___root__hangler[neigh_nr - 1].second);
}

int hedgehogify(int stone_idx, int curr_root_idx, vector<set<int> >& node_idx___neigh_idxes) {
    int neigh_nr = node_idx___neigh_idxes[curr_root_idx].size();
    // cout << "*" << neigh_nr << endl;
    if (neigh_nr == 1) {
        return curr_root_idx;
    }
    int center_idx = curr_root_idx;
    for (auto neigh_idx: node_idx___neigh_idxes[curr_root_idx]) {
        if (neigh_idx != stone_idx) {
            center_idx = hedgehogify(curr_root_idx, neigh_idx, node_idx___neigh_idxes);
            // printf("**%d\n", center_idx);
        }
    }
    printf("%d %d %d\n", stone_idx + 1, curr_root_idx + 1, center_idx + 1);
    operations_made++;
    return center_idx;
}

int straighten_and_hedgehogify_parts(vector<vector<int> >& node_idx___neigh_idxes, int centroid1, int centroid2, bool fl) {
    int nodes_nr = node_idx___neigh_idxes.size();
    int neutral_idx = centroid1;
    vector<set<int> > curr_node_idx___neigh_idxes(nodes_nr);
    vector<int> curr_node_idx___is_visited(nodes_nr, 0);
    for (auto neigh_idx : node_idx___neigh_idxes[centroid1]) {
        if ((neigh_idx == centroid2) || (neigh_idx == centroid1)) {
            continue;
        }
        curr_node_idx___neigh_idxes[centroid1].insert(neigh_idx);
        curr_node_idx___neigh_idxes[neigh_idx].insert(centroid1);
        stack<int> dfs_stack;
        dfs_stack.push(neigh_idx);
        curr_node_idx___is_visited[neigh_idx] = 1;
        while (!dfs_stack.empty()) {
            int curr_node_idx = dfs_stack.top();
            dfs_stack.pop();
            for (auto curr_neigh_idx: node_idx___neigh_idxes[curr_node_idx]) {
                if ((curr_neigh_idx != centroid1) && (curr_node_idx___is_visited[curr_neigh_idx] == 0) && (curr_neigh_idx != centroid2)) {
                    curr_node_idx___neigh_idxes[curr_node_idx].insert(curr_neigh_idx);
                    curr_node_idx___neigh_idxes[curr_neigh_idx].insert(curr_node_idx);
                    curr_node_idx___is_visited[curr_neigh_idx] = 1;
                    dfs_stack.push(curr_neigh_idx);
                }
            }
        }
        pii report = straighten_subtree(centroid1, neigh_idx, curr_node_idx___neigh_idxes);
        neutral_idx = hedgehogify(centroid1, report.first, curr_node_idx___neigh_idxes);
        // for (auto operation : operations) {
        //     cout << operation[0] << " " << operation[1] << " " << operation[2] << endl;
        // }
    }

    if (centroid1 == centroid2) {
        return neutral_idx;
    }
    if (!fl){
        neutral_idx = straighten_and_hedgehogify_parts(node_idx___neigh_idxes, centroid2, centroid1, 1);
    }
    return neutral_idx;
}

void solve() {

    int nodes_nr;
    scanf("%d", &nodes_nr);
    vector<vector<int> > node_idx___neigh_idxes(nodes_nr);
    for_each(edge_idx, 0, nodes_nr - 1, 1) {
        int node1, node2;
        scanf("%d %d", &node1, &node2);
        node1--;
        node2--;
        node_idx___neigh_idxes[node2].push_back(node1);
        node_idx___neigh_idxes[node1].push_back(node2);
    }
    vector<int> centroids = get_centroids(node_idx___neigh_idxes);
    int centroid1, centroid2;
    if (centroids.size() == 1) {
        centroid1 = centroids[0];
        centroid2 = centroids[0];
    }
    else {
        centroid1 = centroids[0];
        centroid2 = centroids[1];
    }
    // cout << "!" << centroid1 << " " << centroid2 << endl;
    vector<vector<int> > operations;
    printf("%d\n", 2 * nodes_nr);
    int neigh_idx = straighten_and_hedgehogify_parts(node_idx___neigh_idxes, centroid1, centroid2, 0);
    while(operations_made < 2 * nodes_nr) {
        printf("%d %d %d\n", centroid2 + 1, neigh_idx + 1, neigh_idx + 1);
        operations_made++;
    }
}

int main() {
    //ios_base::sync_with_stdio(0);
    solve();
}

#include<bits/stdc++.h>
#include<map>
using namespace std;
#define maxn 200005
int n;
int head[maxn],v[maxn*2],suc[maxn*2],en=1;
void addedge(int iu,int iv)
{
    en++;
    suc[en]=head[iu];
    v[en]=iv;
    head[iu]=en;
}
int sz[maxn],ma[maxn],cg[3],ncg;
void getcg(int s,int par)
{
    sz[s]=1;
    ma[s]=0;
    for(int i=head[s];i;i=suc[i])
	if(v[i]!=par){
	    getcg(v[i],s);
	    sz[s]+=sz[v[i]];
	    ma[s]=max(ma[s],sz[v[i]]);
	}
    ma[s]=max(ma[s],n-sz[s]);
    if(ncg==1&&ma[s]==ma[cg[0]]) cg[ncg++]=s;
    if(!ncg||ma[s]<ma[cg[0]]){
	cg[ncg=0]=s;
	cg[++ncg]=0;
    }
}
struct ans
{
    int x,y1,y2;
    ans(int x=0,int y1=0,int y2=0):
	x(x),y1(y1),y2(y2) {}
}st[maxn*2];
int ts,top,cur,G;
void dfs(int s,int par)
{
    for(int i=head[s];i;i=suc[i])
	if(v[i]!=par){
	    dfs(v[i],s);
	}
    //printf("%d\n",s);
    if(par==top||s==top) return;
    st[++ts]=ans(G,cur,s);
    st[++ts]=ans(s,par,top);
    cur=s;
}
int main()
{
    int i,j,k;
    scanf("%d",&n);
    for(i=1;i<n;i++){
	scanf("%d%d",&j,&k);
	addedge(j,k);
	addedge(k,j);
    }
    getcg(1,0);
    //printf("%d %d %d\n",ncg,cg[0],cg[1]);
    for(i=0;i<ncg;i++)
	for(j=head[cg[i]];j;j=suc[j]){
	    if(v[j]==cg[i^1]) continue;
	    cur=top=v[j]; G=cg[i];
	    dfs(top,cg[i]);
	    if(cur!=top) st[++ts]=ans(G,cur,top);
	}
    printf("%d\n",ts);
    for(i=1;i<=ts;i++)
	printf("%d %d %d\n",st[i].x,st[i].y1,st[i].y2);
    return 0;
}

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

using namespace __gnu_cxx;

using ll = long long;
using vi = vector<int>;
using db = double;
#define pb push_back
#define fir first
#define sec second

const int N = 2e5L + 11;
vector <int> e[N];

int n;

int pr[N], sz[N];
void dfs1(int x, int p) {
	pr[x] = p; sz[x] = 1;
	for(int i : e[x]) if(i != p) {
		dfs1(i, x);
		sz[x] += sz[i];
	}
}

vector <pair <int, pair <int, int>>> ans;

int nxt[N][2];
rope <int> r[N], ir[N];

void dfs2(int x, int p) {
	int sc = 0;
	for(int i : e[x]) if(i != p) {
		sc ++;
		dfs2(i, x);
	}
	if(!sc) {
		r[x] = ir[x] = {x};
	} else {
		r[x] = ir[x] = {x}; int l = p;
		vector <int> v;
		for(int i : e[x]) if(i != p) {
			v.pb(i);
		}
		r[x] = ir[v[0]]; ir[x] = r[v[0]]; ans.pb({p, {x, ir[v[0]][0]}}); l = r[v[0]][0];
		for(int i = 1; i < v.size(); i ++) {
			ans.pb({l, {x, ir[v[i]][0]}});
			r[x] = r[x] + ir[v[i]];
			ir[x] = r[v[i]] + ir[x];
			l = ir[x][0];
		}
		r[x] += x;
		ir[x] = rope<int>{x} + ir[x];
	}
}

void solve(rope <int> r, int p) {
	vi v;
	//cout << "!\n"; for(int x : r) cout << x << ' '; cout << '\n';
	for(int x : r) v.pb(x);
	for(int i = (int)v.size() - 2; i >= 0; i --)
		ans.pb({v[i], {v[i + 1], v.back()}});
	ans.pb({p, {v[0], v.back()}});
}

int main() {
	ios :: sync_with_stdio(0);
	cin >> n;
	for(int i = 1; i < n; i ++) {
		int u, v; cin >> u >> v;
		e[u].pb(v); e[v].pb(u);
	}

	dfs1(1, 0);

	int r = -1;
	for(int i = 1; i <= n; i ++) {
		bool f = 1;
		for(int s : e[i]) if(s != pr[i])
			if(sz[s] * 2 >= n) f = 0;
		if((n - sz[i]) * 2 >= n) f = 0;
		if(f) r = i;
	}

	//cout << r << '\n';

	if(r != -1) {
		for(int i : e[r]) {
			dfs2(i, r); solve(::r[i], r);
		}
	} else {
		for(int i = 2; i <= n; i ++) if(sz[i] * 2 == n) {
			for(int j : e[i]) if(j != pr[i]) {
				dfs2(j, i); solve(::r[j], i);
			}
			for(int j : e[pr[i]]) if(j != i) {
				dfs2(j, pr[i]); solve(::r[j], pr[i]);
			}
			break;
		}
	}

	auto v = ans; ans = {};
	for(auto p : v) if(p.sec.fir != p.sec.sec) ans.pb(p);
	cout << ans.size() << '\n';
	for(auto p : ans)
		cout << p.fir << ' ' << p.sec.fir << ' ' << p.sec.sec << '\n';

	return 0;
}

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<map>
#define LL long long
using namespace std;
const int MAXB = 1e7;
char buf[MAXB], *cp = buf;
inline void rd(int &x){
	x = 0; int f = 1;
	while(*cp < '0' || '9' < *cp){if(*cp == '-') f = -1; cp++;}
	while('0' <= *cp && *cp <= '9') x = (x << 3) + (x << 1) + *cp - 48, cp++;
	x *= f;
}
const int MAXN = 200010;
int n, rt[2], cnt;
vector<int> G[MAXN];
int sz[MAXN];
int mx[MAXN];
int S, L, k;
struct Triple{
	int x, y, z;
	Triple(){}
	Triple(int x, int y, int z): x(x), y(y), z(z){}
}ans[MAXN << 1];
void dfs(int x){
	sz[x] = 1; mx[x] = 0;
	for(register unsigned int i = 0; i < G[x].size(); i++){
		int y = G[x][i];
		if(sz[y]) continue;
		dfs(y);
		sz[x] += sz[y];
		mx[x] = max(mx[x], sz[y]);
	}
	mx[x] = max(mx[x], n - sz[x]);
}
void dfs2(int x, int f){
	if(f != S){
		ans[cnt++] = Triple(S, L, x);
		ans[cnt++] = Triple(x, f, k);
		L = x;
	}
	for(unsigned int i = 0; i < G[x].size(); i++)
		if(G[x][i] != f) dfs2(G[x][i], x);
}
void solve(int u, int v){
	S = u;
	for(unsigned int i = 0; i < G[u].size(); i++)
	if(G[u][i] != v){
		k = L = G[u][i];
		dfs2(k, u);
		ans[cnt++] = Triple(u, L, k);
	}
}
int main(){
	//freopen("in.txt", "r", stdin);
	fread(buf, 1, MAXB, stdin);
	rd(n);
	for(int i = 1; i < n; i++){
		int x, y;
		rd(x); rd(y);
		G[x].push_back(y);
		G[y].push_back(x);
	}
	dfs(1);
	rt[0] = 1; rt[1] = 0;
	for(int i = 2; i <= n; i++) if(mx[i] < mx[rt[0]]) rt[0] = i; else if(mx[i] * 2 == n) rt[1] = i;
	solve(rt[0], rt[1]); if(rt[1]) solve(rt[1], rt[0]);

	printf("%d\n", cnt);
	for(int i = 0; i < cnt; i++)
		printf("%d %d %d\n", ans[i].x, ans[i].y, ans[i].z);
	return 0;
}

#include <stdio.h>
#include <vector>
using namespace std;
const int N=200050;
vector<int> Tree[N];
int Size[N];
int n;
int isCentroid[N];
vector<int> Cen;
void CalcSize(int cur, int prev)
{
	Size[cur]=1;
	isCentroid[cur]=true;
	int i;
	for(i=0;i<Tree[cur].size();i++)
	{
		int v=Tree[cur][i];
		if(v!=prev)
		{
			CalcSize(v,cur);
			Size[cur]+=Size[v];
			if(Size[v]>n/2) isCentroid[cur]=false;
		}
	}
	if(n-Size[cur]>n/2) isCentroid[cur]=false;
	if(isCentroid[cur]) Cen.push_back(cur);
}
struct Data
{
	int x,y,y1;
	Data (){}
	Data (int a, int b, int c)
	{
		x=a;
		y=b;
		y1=c;
	}
};
vector<Data> ans;
int last;
void Solve(int cur, int prev, int cen, int first)
{
	if(cur!=first)
	{
		ans.push_back(Data(cen,last,cur));
		ans.push_back(Data(cur,prev,first));
		last=cur;
	}
	int i;
	for(i=0;i<Tree[cur].size();i++)
	{
		int v=Tree[cur][i];
		if(v!=prev)
		{
			Solve(v,cur,cen,first);
		}
	}
}
int main()
{
	int i,u,v,j;
	scanf("%i",&n);
	for(i=0;i<n-1;i++)
	{
		scanf("%i %i",&u,&v);
		Tree[u].push_back(v);
		Tree[v].push_back(u);
	}
	CalcSize(1,1);
	for(i=0;i<Cen.size();i++)
	{
		u=Cen[i];
		for(j=0;j<Tree[u].size();j++)
		{
			v=Tree[u][j];
			if(!isCentroid[v])
			{
				last=v;
				Solve(v,u,u,v);
				ans.push_back(Data(u,last,v));
			}
		}
	}
	printf("%i\n",ans.size());
	for(i=0;i<ans.size();i++)
	{
		printf("%i %i %i\n",ans[i].x,ans[i].y,ans[i].y1);
	}
	return 0;
}

#include<cstdio>
const int N=200005;
struct edge{
	int to,next;
}e[N<<1];
int h[N],n,xb,a,b,i,j,rt,rt2,sz[N],f[N],dfn[N],x[N<<1],y[N<<1],z[N<<1],k,dad[N],lst;
inline void addedge(int a,int b){
	e[++xb]=(edge){b,h[a]};
	h[a]=xb;
	e[++xb]=(edge){a,h[b]};
	h[b]=xb;
}
inline void up(int&a,int b){
	if(a<b)a=b;
}
void dfs(int x,int fa){
	sz[x]=f[x]=1;
	for(int i=h[x];i;i=e[i].next)if(e[i].to!=fa)dfs(e[i].to,x),sz[x]+=sz[e[i].to],up(f[x],sz[e[i].to]);
	up(f[x],n-sz[x]);
	if(f[x]<b)rt=x,rt2=0,b=f[x];
		else if(f[x]==b)rt2=x;
}
void getv(int x,int fa){
	if(fa!=e[i].to && x!=e[i].to)dfn[++xb]=x,dad[xb]=fa;
	for(int j=h[x];j;j=e[j].next)if(e[j].to!=fa)getv(e[j].to,x);
}
int main(){
	scanf("%d",&n);
	for(i=1;i<n;++i){
		scanf("%d%d",&a,&b);
		addedge(a,b);
	}
	b=1<<30;
	dfs(1,0);
	for(i=h[rt];i;i=e[i].next)
		if(e[i].to!=rt2){
			xb=0;
			getv(lst=e[i].to,rt);
			for(j=1;j<=xb;++j){
				x[++k]=rt,y[k]=lst,z[k]=dfn[j];
				x[++k]=dfn[j],y[k]=dad[j],z[k]=e[i].to;
				lst=dfn[j];
			}
			x[++k]=rt,y[k]=lst,z[k]=e[i].to;
		}
	if(rt2)for(i=h[rt2];i;i=e[i].next)
		if(e[i].to!=rt){
			xb=0;
			getv(lst=e[i].to,rt2);
			for(j=1;j<=xb;++j){
				x[++k]=rt2,y[k]=lst,z[k]=dfn[j];
				x[++k]=dfn[j],y[k]=dad[j],z[k]=e[i].to;
				lst=dfn[j];
			}
			x[++k]=rt2,y[k]=lst,z[k]=e[i].to;
		}
	printf("%d\n",k);
	for(i=1;i<=k;++i)printf("%d %d %d\n",x[i],y[i],z[i]);
	return 0;
}

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<queue>
using namespace std;
typedef long long LL;
#define sqr(x) ((x)*(x))
#define mp make_pair
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
	int x = 0; char ch = gc(); bool positive = 1;
	for (; !isdigit(ch); ch = gc())	if (ch == '-')	positive = 0;
	for (; isdigit(ch); ch = gc())	x = x * 10 + ch - '0';
	return positive ? x : -x;
}
inline void write(int a){
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
inline void writeln(int a){
    if(a<0){
    	a=-a; putchar('-');
	}
	write(a); puts("");
}
const int N=200005;
int nedge,peo[N],f[N],father[N],q[N],tot,top,son[N],nextt[N<<1],ed[N<<1],sum,vis[N],n;
int ans[N*2][3],gen[N];
inline void aedge(int a,int b){
	nextt[++nedge]=son[a]; son[a]=nedge; ed[nedge]=b;
}
void get(int p,int fa){
	peo[p]=1; f[p]=0;
	for(int i=son[p];i;i=nextt[i])if(!vis[ed[i]]&&ed[i]!=fa){
		get(ed[i],p); peo[p]+=peo[ed[i]]; f[p]=max(f[p],peo[ed[i]]);
	}
	f[p]=max(f[p],sum-peo[p]); if(f[p]*2<=n)gen[p]=vis[p]=1;
}
void solve(int p){
	vis[p]=1;
	for(int i=son[p];i;i=nextt[i])if(!vis[ed[i]]){
		father[ed[i]]=p; solve(ed[i]);
	}
	q[++top]=p;
}
int main(){
	n=read(); f[0]=1e9;
	for(int i=1;i<n;i++){
		int a=read(),b=read();
		aedge(a,b); aedge(b,a);
	}
	sum=n; get(1,0);
	for(int i=1;i<=n;i++)if(gen[i]){
		for(int j=son[i];j;j=nextt[j])if(!gen[ed[j]]){
			top=0; solve(ed[j]);
			ans[++tot][0]=i; ans[tot][1]=ed[j]; ans[tot][2]=q[1];
			for(int j=2;j<=top;j++){
				ans[++tot][0]=q[j-1]; ans[tot][1]=father[q[j-1]]; ans[tot][2]=q[j];
			}
			for(int j=top-1;j;j--){
				ans[++tot][0]=q[j]; ans[tot][1]=q[j+1]; ans[tot][2]=q[top];
			}
			//cout<<q[top]<<" axs "<<ed[j]<<endl;
			ans[++tot][0]=i; ans[tot][1]=q[1]; ans[tot][2]=q[top];
		}
	}
	sum=0;
	for(int i=1;i<=tot;i++)if(ans[i][1]!=ans[i][2])sum++;
	writeln(sum);
	for(int i=1;i<=tot;i++)if(ans[i][1]!=ans[i][2]){
		write(ans[i][0]); putchar(' '); write(ans[i][1]); putchar(' '); writeln(ans[i][2]);
	}
}

#include<bits/stdc++.h>
#define mp(a,b) make_pair((a),(b))
#define pii pair<int,int>
//#define pdd pair<double,double>
#define pll pair<LL,LL>
#define pb(x) push_back(x)
#define x first
#define y second
#define sqr(x) ((x)*(x))
#define EPS 1e-8
#define mii map<int,int>
#define MEM(x) memset(x,0,sizeof(x))
#define MEMS(x) memset(x,-1,sizeof(x))
#define N 500005
//#define M 1000005
#define pi 3.14159265359
#define cpdd const pdd
#define hash Hash
#define list List
using namespace std;
typedef long long LL;
using namespace std;
vector<int> v[200005];
int Size[200005];
int Min;
vector<int> center;
int n;
void find_center(int a,int f){
	int Max=0,sum=1;
	for(vector<int>::iterator it=v[a].begin();it!=v[a].end();it++){
		if(*it!=f){
			find_center(*it,a);
			sum+=Size[*it];
			Max=max(Max,Size[*it]);
		}
	}
	Max=max(Max,n-sum);
	Size[a]=sum;
//	printf("%d %d %d\n",a,Size[a],Max);
	if(Max<Min){
		Min=Max;
		center.clear();
	}
	if(Max==Min){
		center.pb(a);
	}
}
vector<pair<pii,int> > ans;
pii dfs(int a,int f){
	//printf("a:%d\n",a);
	vector<int> vi;
	for(vector<int>::iterator it=v[a].begin();it!=v[a].end();it++){
		if(*it!=f){
			pii p=dfs(*it,a);
		//	printf("%d %d %d\n",a,*it,p.x);
			*it=p.x;
			vi.pb(p.y);
		}
	}
	//printf("%d",a);
	int fa=f;
	int cnt=0;
	for(int i=0;i-cnt<vi.size();i++){
		//printf("%d: %d",a,v[a][i]);
		if(v[a][i]!=f){
			ans.pb(mp(mp(fa,a),vi[i-cnt]));
			v[vi[i-cnt]].pb(fa);
			if(fa!=f)
			for(vector<int>::iterator it=v[fa].begin();it!=v[fa].end();it++){
				if(*it==a){
					*it=vi[i-cnt];
				}
			}
			fa=v[a][i];
		}
		else
		cnt++;
	}
	//printf("%d",a);
	v[a].clear();
	v[a].pb(fa);
	//printf("%d %d\n",a,fa);
	if(vi.empty())
	vi.pb(a);
	return mp(vi[0],a);
}
int dfs2(int a,int f){
//	printf("%d %d\n",a,f);
//	system("PAUSE");
	int ret=a;
	for(vector<int>::iterator it=v[a].begin();it!=v[a].end();it++){
		if(*it!=f){
			int p=dfs2(*it,a);
			ans.pb(mp(mp(a,*it),p));
			ret=p;
		}
	}
	return ret;
}
int main(){
	Min=1e9;
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		int a,b;
		scanf("%d %d",&a,&b);
		v[a].pb(b);
		v[b].pb(a);
	}
	find_center(1,0);
	if(center.size()==1){
		for(vector<int>::iterator it=v[center[0]].begin();it!=v[center[0]].end();it++){
		//	printf("%d ",*it);
			*it=dfs(*it,center[0]).x;
		//	printf("%d",*it);
			int p=dfs2(*it,center[0]);
			ans.pb(mp(mp(center[0],*it),p));
		//	printf("ok\n");
		}
	}
	else{
		for(int i=0;i<2;i++){
			for(vector<int>::iterator it=v[center[i]].begin();it!=v[center[i]].end();it++){
				if(*it==center[i^1])
				continue;
				*it=dfs(*it,center[i]).x;
				int p=dfs2(*it,center[i]);
				ans.pb(mp(mp(center[i],*it),p));
			}
		}
	}
	printf("%d\n",ans.size());
	for(int i=0;i<ans.size();i++){
		printf("%d %d %d\n",ans[i].x.x,ans[i].x.y,ans[i].y);
	}
}

#include "bits/stdc++.h"
using namespace std;
const int N = 2e5 + 5;
int n;
int a , b;
vector < int > v[N];
int subtree[N];
void dfs1(int node , int parent){
	subtree[node] = 1;
	for(int next : v[node]){
		if(next != parent){
			dfs1(next , node);
			subtree[node] += subtree[next];
		}
	}
}
int find(int node , int parent){
	for(int next : v[node]){
		if(next != parent && subtree[next] > (n >> 1)){
			return find(next , node);
		}
	}
	return node;
}
vector < pair < int , pair < int , int > > > ans;
int root , cur , who;
void dfs2(int node , int parent){
	//cout << node << " " << parent << " " << cur << " " << who << endl;
	ans.push_back({root , {cur , node}});
	ans.push_back({node , {parent , who}});
	cur = node;
	for(int next : v[node]){
		if(next != parent){
			dfs2(next , node);
		}
	}
}
void actuallysolve(int child , int node){
	root = node;
	cur = child;
	who = child;
	for(int next1 : v[child]){
		if(next1 != node){
			for(int next2 : v[next1]){
				if(next2 != child){
					dfs2(next2 , next1);
				}
			}
		}
	}
	ans.push_back({root , {cur , who}});
}
void solve(int node , int parent){
	for(int next : v[node]){
		if(next != parent){
			actuallysolve(next , node);
		}
	}
}
int main(){
	scanf("%d" , &n);
	for(int i = 1 ; i < n ; ++i){
		scanf("%d %d" , &a , &b);
		v[a].emplace_back(b);
		v[b].emplace_back(a);
	}
	dfs1(1 , 0);
	int cent = find(1 , 0);
	int cent2 = 0;
	for(int next : v[cent]){
		if(subtree[next] * 2 == n){
			cent2 = next;
		}
	}
	solve(cent , cent2);
	if(cent2){
		solve(cent2 , cent);
	}
	printf("%d\n" , int(ans.size()));
	for(auto it : ans){
		printf("%d %d %d\n" , it.first , it.second.first , it.second.second);
	}
}

/*"Level Of ViolencE"*/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef double D;
typedef pair<int,int> Pii;
#define mp(a,b) make_pair(a,b)
#define fir first
#define sec second
inline int min(int _a,int _b){return _a<_b?_a:_b;}
inline int max(int _a,int _b){return _a>_b?_a:_b;}
template<class T>inline void rd(T &_a){
	int _f=0,_ch=getchar();_a=0;
	while(_ch<'0' || _ch>'9'){if(_ch=='-')_f=1;_ch=getchar();}
	while(_ch>='0' && _ch<='9'){_a=(_a<<1)+(_a<<3)+_ch-'0';_ch=getchar();}
	if(_f)_a=-_a;
}
const int inf=0x3f3f3f3f;
const D eps=1e-8;
const int N=2e5+5;
struct node{int v,nt;}e[N<<1];
struct jude{int x,y,z;}a[N<<1];
int h[N],f[N],s[N],rt,l,L,v[N],S,k;
void dfs(int u,int fa){
	s[u]=1;
	for(int i=h[u];i;i=e[i].nt)
		if(e[i].v!=fa && !v[e[i].v]){
			dfs(e[i].v,u);
			s[u]+=s[e[i].v];
			f[u]=max(f[u],s[e[i].v]);
		}
	f[u]=max(f[u],S-s[u]);
	if(f[u]<f[rt])rt=u;
}
void dfs2(int u,int fa){
	if(fa!=S){
		a[l++]=(jude){S,L,u};
		a[l++]=(jude){u,fa,k};
		L=u;
	}
	for(int i=h[u];i;i=e[i].nt)
		if(e[i].v!=fa)
			dfs2(e[i].v,u);
}
void sl(int u,int fa){
	S=u;
	for(int i=h[u];i;i=e[i].nt)
		if(e[i].v!=fa){
			k=L=e[i].v;
			dfs2(e[i].v,u);
			a[l++]=(jude){u,L,k};
		}
}
int main(){
	//clock_t start=clock();
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	int n,x=0;rd(n);
	for(int i=1,u,v;i<n;i++){
		rd(u);rd(v);
		e[i<<1]=(node){v,h[u]};h[u]=i<<1;
		e[i<<1|1]=(node){u,h[v]};h[v]=i<<1|1;
	}
	S=f[0]=n;dfs(1,0);
	dfs(rt,0);
	for(int i=1;i<=n;i++)
		if(i!=rt && s[i]*2==n)x=i;
	sl(rt,x);
	if(x)sl(x,rt);
	printf("%d\n",l);
	for(int i=0;i<l;i++)
		printf("%d %d %d\n",a[i].x,a[i].y,a[i].z);
	//printf("\n%dms",(int)((double)(clock()-start)/CLOCKS_PER_SEC*1000));
	return 0;
}

#include <iostream>
#include <vector>

using namespace std;

const int limite=1000000;

int n;
vector<int> g[limite];
int numnodos[limite];

int computanumnodos(int u,int p)
{
  numnodos[u]=1;
  vector<int> &ar=g[u];
  for (int i=0;i<int(ar.size());i++) {
    int v=ar[i];
    if (v!=p) numnodos[u]+=computanumnodos(v,u);
  }
  return numnodos[u];
}

int buscacentro(int u,int p)
{
  vector<int> &ar=g[u];
  for (int i=0;i<int(ar.size());i++) {
    int v=ar[i];
    if (v!=p and n<=2*numnodos[v])
      return buscacentro(v,u);
  }
  return u;
}

void eliminapadre(int u,int p)
{
  vector<int> &ar=g[u];
  vector<int> nextar;
  for (int i=0;i<int(ar.size());i++) {
    int v=ar[i];
    if (v!=p) {
      nextar.push_back(v);
      eliminapadre(v,u);
    }
  }
  ar=nextar;
}

struct elem {
  int x,y,yp;
  elem() {}
  elem(int x,int y,int yp):x(x),y(y),yp(yp) {}
};

vector<elem> sol;

void cepillarse(int c,int u)
{
  int connected=u;
  vector<int> &ar=g[u];
  while (int(ar.size())) {
    int v=ar.back();
    vector<int> &arv=g[v];
    if (int(arv.size())==0) {
      ar.pop_back();
    } else {
      int w=arv.back();
      if (w!=connected) {
	sol.push_back(elem(c,connected,w));
	connected=w;
      }
      sol.push_back(elem(w,v,u));
      arv.pop_back();
      ar.push_back(w);
    }
  }
  if (u!=connected)
    sol.push_back(elem(c,connected,u));
}

int main()
{
  ios::sync_with_stdio(false);
  cin>>n;
  for (int i=0;i<n-1;i++) {
    int u,v;
    cin>>u>>v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  computanumnodos(1,0);
  int c=buscacentro(1,0);
  computanumnodos(c,0);
  eliminapadre(c,0);
  vector<int> &ar=g[c];
  for (int i=0;i<int(ar.size());i++) {
    int u=ar[i];
    if (2*numnodos[u]<n)
      cepillarse(c,u);
    else {
      vector<int> &aru=g[u];
      for (int j=0;j<int(aru.size());j++)
	cepillarse(u,aru[j]);
    }
  }
  cout<<int(sol.size())<<endl;
  for (int i=0;i<int(sol.size());i++) {
    elem &e=sol[i];
    cout<<e.x<<" "<<e.y<<" "<<e.yp<<endl;
  }
}

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

	typedef pair<int,int> PII;
	typedef vector<int> VI;
	typedef vector<VI> VVI;
	const int INF = 2000000000;

	VVI adj;
	PII dfsBamboo(int u, const function<void(int,int,int)> &emit, int p = -1){
		vector<PII> leaves;
		for(int v : adj[u]){
			if(v == p)continue;
			leaves.push_back( dfsBamboo(v, emit, u) );
		}
		if(leaves.size() == 0)return PII(u, u);
		for (int i = 0; i < leaves.size(); ++i) {
			if(i == 0){
				emit(p, u, leaves[i].second);
			}else{
				emit(leaves[i-1].first, u, leaves[i].second);
			}
		}
		return PII(leaves[0].second, u);
	}
	int dfsStar(int u, const function<void(int,int,int)> &emit, int p = -1) {
		for(int v : adj[u]){
			if(v == p)continue;
			int nch = dfsStar(v, emit, u);
			emit(p, u, nch);
			return nch;
		}
		return u;

	}
	PII cp(int a, int b){
		return PII(min(a,b), max(a,b));
	}
	int SZ[200010];
	int dfsSize(int u,int p = -1){
		SZ[u] = 1;
		for(int v : adj[u])
			if(v != p)
				SZ[u] += dfsSize(v, u);
		return SZ[u];
	}

	struct Change {
		int u,v0,v1;
	};
	int main()
	{
		int N;
		cin >> N;
		adj = VVI(N);
		set<PII> S;
		for (int i = 0; i < N-1; ++i) {
			int u,v;
			cin >> u >> v;
			u--;v--;
			S.insert(cp(u,v));
			adj[u].push_back(v);
			adj[v].push_back(u);
		}
		dfsSize(0);
		vector<int> CD;

		for (int u = 0; u < N; ++u) {
			int b = 0;
			for(int v : adj[u]){
				int csz = SZ[v] < SZ[u] ? SZ[v] : (N-SZ[u]);
				b = max(b, csz);
			}
			if(b*2 <= N){
				CD.push_back(u);
			}
		}
	//	cout << CD.size() << endl;
		vector<Change> CH;
		for(int c : CD){
			for(int v : adj[c]){
				if(find(CD.begin(), CD.end(), v) != CD.end())continue;
				dfsBamboo(v, [&S, &CH](int u, int v0, int v1) {
					S.erase(cp(u,v0));
					S.insert(cp(u,v1));
	//				if(v0 != v1)
					CH.push_back({u+1, v0+1, v1+1});
				}, c);
			}
		}
		adj = VVI(N);
		for(PII p : S){
			adj[p.first].push_back(p.second);
			adj[p.second].push_back(p.first);
		}
		for(int c : CD){
			for(int v : adj[c]){
				if(find(CD.begin(), CD.end(), v) != CD.end())continue;
				dfsStar(v, [&S, &CH](int u, int v0, int v1) {
					S.erase(cp(u,v0));
					S.insert(cp(u,v1));
	//				if(v0 != v1)
					CH.push_back({u+1, v0+1, v1+1});
				}, c);
			}
		}
		cout << CH.size() << endl;
		for(Change &c : CH)
			cout << c.u << " " << c.v0 << " " << c.v1 << endl;
	}

#include <bits/stdc++.h>
#ifdef DEMETRIO
#define deb(...) fprintf(stderr,__VA_ARGS__)
#define deb1(x) cerr << #x << " = " << x << endl
#else
#define deb(...) 0
#define deb1(x) 0
#endif
#define pb push_back
#define mp make_pair
#define fst first
#define snd second
#define fore(i,a,b) for(int i=a,ThxDem=b;i<ThxDem;++i)
#define SZ(x) ((int)x.size())
using namespace std;
typedef long long ll;

#define MAXN 200005

vector<pair<int,pair<int,int> > > r;
vector<int> g2[MAXN];

ll dfs2(int x, int d){
	ll r=1LL*d*d;
	for(int y:g2[x])r+=dfs2(y,d+1);
	return r;
}

vector<int> g[MAXN];int n;
bool tk[MAXN];
int fat[MAXN]; // father in centroid decomposition
int szt[MAXN]; // size of subtree
int calcsz(int x, int f){
	szt[x]=1;
	for(auto y:g[x])if(y!=f&&!tk[y])szt[x]+=calcsz(y,x);
	return szt[x];
}
bool dfss(int x, int f, int q){
	for(int y:g[x]){
		if(y==q)return true;
		if(!tk[y]&&y!=f&&dfss(y,x,q))return true;
	}
	return false;
}
int ff[MAXN];
bool dfs3(int x, int f, vector<int>& v){
	v.pb(x);ff[x]=f;
	for(int y:g[x])if(y!=f)dfs3(y,x,v);
}
void cdfs(int x=0, int f=-1, int sz=-1){ // O(nlogn)
	if(sz<0)sz=calcsz(x,-1);
	for(auto y:g[x])if(!tk[y]&&szt[y]*2>=sz){
		szt[x]=0;cdfs(y,f,sz);return;
	}
	int z=-1;
	sz=calcsz(x,-1);
	for(int y:g[x])if(!tk[y]&&szt[y]*2>=sz){z=y;break;}
	tk[x]=true;fat[x]=f;
	if(z>=0)tk[z]=true,fat[z]=f;
	for(int y:g[x])if(!tk[y]){
		vector<int> v;
		dfs3(y,x,v);
		int p=y;
		for(int a:v)if(a!=y){
			r.pb(mp(x,mp(p,a)));
			if(ff[a]!=y)r.pb(mp(a,mp(ff[a],y)));
			p=a;
		}
		if(p!=y)r.pb(mp(x,mp(p,y)));
	}
	if(z>=0){
		for(int y:g[z])if(!tk[y]){
			vector<int> v;
			dfs3(y,z,v);
			int p=y;
			for(int a:v)if(a!=y){
				r.pb(mp(z,mp(p,a)));
				if(ff[a]!=y)r.pb(mp(a,mp(ff[a],y)));
				p=a;
			}
			if(p!=y)r.pb(mp(z,mp(p,y)));
			//printf("  %d %d %d\n",r.back().fst+1,r.back().snd.fst+1,r.back().snd.snd+1);
		}
	}
}
void centroid(){memset(tk,false,sizeof(tk));cdfs();}

int main(){
	while(scanf("%d",&n)!=EOF){
		fore(i,1,n){
			int x,y;
			scanf("%d%d",&x,&y);x--;y--;
			g[x].pb(y);
			g[y].pb(x);
		}
		centroid();
		//reverse(r.begin(),r.end());
		printf("%d\n",SZ(r));
		for(auto p:r)printf("%d %d %d\n",p.fst+1,p.snd.fst+1,p.snd.snd+1);
		r.clear();
		fore(i,0,n)g[i].clear(),g2[i].clear();
		puts("");
	}
	return 0;
}

#include "bits/stdc++.h"
using namespace std;
const int maxn = 202020;
vector<int> tr[maxn];
int sz[maxn], par[maxn], dep[maxn];
void dfs(int cur, int pr){
	par[cur] = pr;
	sz[cur] = 1;
	for(int nxt : tr[cur]){
		if(nxt == pr) continue;
		dep[nxt] = dep[cur] + 1;
		dfs(nxt, cur);
		sz[cur] += sz[nxt];
	}
}
vector<tuple<int,int,int> > o;
int sons[maxn];
queue<int> q;
void push_build(int cur, int pr){
	par[cur] = pr;
	for(int nxt : tr[cur]){
		if(nxt == pr) continue;
		dep[nxt] = dep[cur] + 1;
		push_build(nxt, cur);
		sons[cur]++;
	}
	if(sons[cur] == 0) q.push(cur);
}
void build(int cur, int pr){
	for(int nxt : tr[cur]){
		if(nxt == pr) continue;
		assert(q.empty());
		dep[nxt] = 1;
		push_build(nxt, cur);
		int bad = nxt;
		while(!q.empty()){
			int now = q.front(); q.pop();
			if(dep[now] < 3) continue;
			o.push_back(make_tuple(cur, bad, now));
			o.push_back(make_tuple(now, par[now], nxt));
			bad = now;
			if(--sons[par[now]] == 0) q.push(par[now]);
		}
		if(bad != nxt){
			o.push_back(make_tuple(cur, bad, nxt));
		}
	}
}
int main(){
	int n;
	scanf("%d", &n);
	for(int e = 0; e < n - 1; e++){
		int u, v;
		scanf("%d %d", &u, &v);
		tr[u].push_back(v);
		tr[v].push_back(u);
	}
	dfs(1, 0);
	vector<int> cen;
	for(int e = 1; e <= n; e++){
		int mx = n - sz[e];
		for(int nxt : tr[e]){
			if(nxt == par[e]) continue;
			mx = max(mx, sz[nxt]);
		}
		if(mx <= n / 2) cen.push_back(e);
	}
	if(cen.size() == 1){
		build(cen[0], 0);
	} else {
		build(cen[0], cen[1]);
		build(cen[1], cen[0]);
	}
	printf("%d\n", (int)o.size());
	for(auto e : o){
		int u, v, w;
		tie(u, v, w) = e;
		printf("%d %d %d\n", u, v, w);
	}
	return 0;
}

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define fio ios_base::sync_with_stdio(false)
#define pdl cout << "*" << endl
#define MOD 1000000007
#define INF 1000000000
#define INFLL 1000000000000000000ll
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
#define long int64_t
using namespace std;
using namespace __gnu_pbds;
typedef pair<int, int> pii;
typedef pair<long, long> pll;
typedef priority_queue<int, vector<int>, greater<int>> min_pq;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> OST;

const int N = 200001;

vector<pair<int, pii>> ans;
vector<int> tr[N];
int sz[N], n, rem;

int dfs(int node = 1, int p = 0)
{
	sz[node] = 1;
	for(int &it : tr[node])
		if(it != p)
			sz[node] += dfs(it, node);
	return sz[node];
}

pii find_centroid(int node = 1, int p = 0)
{
	int ms = 0, hc = 0;
	for(int &it : tr[node])
	{
		if(it != p)
		{
			if(sz[it] > ms)
			{
				ms = sz[it];
				hc = it;
			}
		}
	}
	if(2 * ms <= n)
		return mp(node, int(2 * ms == n) * hc);
	return find_centroid(hc, node);
}

void tf(int node, int p, list<int> &l)
{
	for(int &it : tr[node])
	{
		if(it != p)
		{
			tf(it, node, l);
			ans.pb(mp(l.back(), mp(rem, it)));
			l.pb(it);
			rem = node;
		}
	}
}

int main()
{
	fio;
	cin >> n;
	for(int i=1; i<n; i++)
	{
		int a, b;
		cin >> a >> b;
		tr[a].pb(b);
		tr[b].pb(a);
	}
	dfs();
	pii C = find_centroid();
	list<int> l;
	for(int &it : tr[C.ff])
	{
		if(it != C.ss)
		{
			l.pb(C.ff);
			rem = it;
			tf(it, C.ff, l);
			l.pb(it);
			l.pop_back();
			int c = l.back(), prev;
			l.pop_back();
			if(!l.empty())
			{
				prev = l.back();
				l.pop_back();
			}
			while(!l.empty())
			{
				ans.pb(mp(l.back(), mp(prev, c)));
				prev = l.back();
				l.pop_back();
			}
		}
	}
	for(int &it : tr[C.ss])
	{
		if(it != C.ff)
		{
			l.pb(C.ss);
			rem = it;
			tf(it, C.ss, l);
			l.pb(it);
			l.pop_back();
			int c = l.back(), prev;
			l.pop_back();
			if(!l.empty())
			{
				prev = l.back();
				l.pop_back();
			}
			while(!l.empty())
			{
				ans.pb(mp(l.back(), mp(prev, c)));
				prev = l.back();
				l.pop_back();
			}
		}
	}
	cout << ans.size() << endl;
	for(auto &it : ans)
		cout << it.ff << ' ' << it.ss.ff << ' ' << it.ss.ss << endl;
	return 0;
}

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <sstream>
#include <string>
#include <map>
#include <set>
#include <stdlib.h>
#include <cmath>
#include <math.h>
#include <fstream>
#include <bitset>
#include <queue>
#include <ctime>
#define int long long
using namespace std;
int INF = 1e18;
int maximum, n, ai, bi;
struct Vertex{int l; int r; int pr; int sz; int value; bool p;};
vector<Vertex> decart;
vector<vector<int> > data, ne, ans;
vector<pair<int, int> > edges;
vector<int> h, bases;
vector<bool> orient;
pair<int, int> SP = make_pair(-1, -1);
void update(int vertex){
    if (vertex == -1) return;
    int sz = 1;
    if (decart[vertex].l != -1){
        sz += decart[decart[vertex].l].sz;
    }
    if (decart[vertex].r != -1){
        sz += decart[decart[vertex].r].sz;
    }
    decart[vertex].sz = sz;
}
void push(int vertex){
    if (vertex == -1) return;
    if (!decart[vertex].p) return;
    decart[vertex].p = false;
    swap(decart[vertex].l, decart[vertex].r);
    if (decart[vertex].l != -1){
		decart[decart[vertex].l].p ^= 1;
    }
    if (decart[vertex].r != -1){
		decart[decart[vertex].r].p ^= 1;
    }
}
pair<int, int> split(int father, int number){
    if (father == -1) return SP;
    push(father);
    int l = 1;
    if (decart[father].l != -1){
        l += decart[decart[father].l].sz;
    }
    if (l <= number){
        pair<int, int> p = split(decart[father].r, number - l);
        decart[father].r = p.first;
        p.first = father;
        update(father);
        return p;
    }
    pair<int, int> p = split(decart[father].l, number);
    decart[father].l = p.second;
    p.second = father;
    update(father);
    return p;
}
int merg(int first, int second){
    push(first);
    push(second);
    if (first == -1) return second;
    if (second == -1) return first;
    if (decart[first].pr >= decart[second].pr){
        int v = merg(decart[first].r, second);
        decart[first].r = v;
        update(first);
        return first;
    }
    int v = merg(first, decart[second].l);
    decart[second].l = v;
    update(second);
    return second;
}
int dfs(int vertex, int last){
	int g = 1;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (last == to) continue;
        int num_e = ne[vertex][i];
        if (edges[num_e].first != vertex) orient[num_e] = false;
		g += dfs(to, vertex);
	}
	h[vertex] = g;
	return g;
}
int get_left(int vertex){
	push(vertex);
	if (decart[vertex].l == -1) return decart[vertex].value;
	return get_left(decart[vertex].l);
}
int get_right(int vertex){
	push(vertex);
	if (decart[vertex].r == -1) return decart[vertex].value;
	return get_right(decart[vertex].r);
}
void form(int vertex, int e, int last){
	int ff = vertex;
	Vertex v = {-1, -1, rand(), 1, e, false};
	decart.push_back(v);
	int num = decart.size() - 1;
	int lastv;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (last == to) continue;
		lastv = i;
	}
    for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (last == to) continue;
		form(to, ne[vertex][i], vertex);
		if (i == lastv){
			num = merg(num, bases[to]);
			continue;
		}
		int me = get_right(num);
		int b = bases[to];
		decart[b].p ^= 1;
        int ed = get_left(b);
        int so;
        if (orient[ed]) so = edges[ed].second;
        else so = edges[ed].first;
        int drv;
        if (edges[me].first == vertex) drv = edges[me].second;
        else drv = edges[me].first;
        vector<int> help;
        help.push_back(drv);
        help.push_back(vertex);
        help.push_back(so);
        ans.push_back(help);
        if (edges[me].first == vertex){
			edges[me].first = so;
		}
		else edges[me].second = so;
		num = merg(num, b);
    }
    bases[vertex] = num;
}
void solve(int vertex, int sec){
	vector<int> sv;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (to == sec) continue;
		sv.push_back(to);
        form(data[vertex][i], ne[vertex][i], vertex);
	}
	if (sec != -1){
	for (int i=0; i < data[sec].size(); i++){
		int to = data[sec][i];
		if (to == vertex) continue;
		sv.push_back(to);
        form(data[sec][i], ne[sec][i], sec);
	}
	}
	for (int i=0; i < sv.size(); i++){
		int to = sv[i];
        int b = bases[to];
        int sz = decart[b].sz;
        if (sz <= 2) continue;
        pair<int, int> p = split(b, sz-1);
        pair<int, int> p1 = split(p.first, sz-2);
        int ov, ev;
        int N = decart[p.second].value;
        int V = decart[p1.second].value;
        if ((edges[N].first == edges[V].second) || (edges[N].second == edges[V].second)){
			ov = edges[V].second;
			ev = edges[V].first;
        }
        if ((edges[N].first == edges[V].first) || (edges[N].second == edges[V].first)){
			ev = edges[V].second;
			ov = edges[V].first;
        }
        b = p1.first;
        while (b != -1){
            pair<int, int> p = split(b, decart[b].sz - 1);
			b = p.first;
			int W = decart[p.second].value;
			if (edges[W].first == ev){
                vector<int> help;
                help.push_back(edges[W].second);
                help.push_back(edges[W].first);
                help.push_back(ov);
                ans.push_back(help);
                ev = edges[W].second;
			}
			else{
				vector<int> help;
                help.push_back(edges[W].first);
                help.push_back(edges[W].second);
                help.push_back(ov);
                ans.push_back(help);
                ev = edges[W].first;
			}
        }
	}
}
void get_centroid(int vertex){
	maximum = 0;
	int wh;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		int res = dfs(to, vertex);
		if (res > maximum){
			maximum = res;
			wh = to;
		}
	}
	int ll = vertex;
	while (maximum*2 >= n){
		int mm = 0, vv;
		for (int i=0; i < data[wh].size(); i++){
			int to = data[wh][i];
			if (to == ll) continue;
			if (h[to] > mm){
				mm = h[to];
				vv = to;
			}
		}
        maximum = mm;
        ll = wh;
        wh = vv;
	}
	dfs(ll, -1);
	int se = -1;
	for (int i=0; i < data[ll].size(); i++){
		int to = data[ll][i];
        if (2 * h[to] >= n){
			se = to;
        }
	}
    solve(ll, se);
}
int32_t main(){
    cin >> n;
    for (int i=0; i < n; i++){
		vector<int> help, hh;
		h.push_back(0);
		ne.push_back(hh);
		bases.push_back(-1);
		orient.push_back(true);
		data.push_back(help);
    }
    for (int i=0; i < n-1; i++){
		cin >> ai >> bi;
		data[ai-1].push_back(bi-1);
		data[bi-1].push_back(ai-1);
		ne[ai-1].push_back(i);
		ne[bi-1].push_back(i);
		edges.push_back(make_pair(ai-1, bi-1));
    }
    get_centroid(0);
    cout << ans.size() << endl;
    for (int i=0; i < ans.size(); i++){
		cout << ans[i][0] + 1 << " " << ans[i][1] + 1 << " " << ans[i][2] + 1 << endl;
    }
	return 0;
}

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cmath>
#include <list>
#include <vector>
#include <algorithm>

using namespace std;
typedef long double ld;

const int MSIZE = 2e5;
int n;
int cnt[MSIZE];
vector<int> g[MSIZE];

int c1 = -1, c2 = -1;

void count(int v, int p = -1) {
	cnt[v]++;
	bool flag = true;
	for (int to : g[v])
		if (to != p) {
			count(to, v);
			if (cnt[to] * 2 > n)
				flag = false;
			cnt[v] += cnt[to];
		}
	if ((n - cnt[v]) * 2 > n)
		flag = false;
	if (flag) {
		if (c1 == -1)
			c1 = v;
		else
			c2 = v;
	}
}

vector<pair<int, int> > out;

void dfs_out(int v, int p) {
	for (int to : g[v])
		if (to != p)
			dfs_out(to, v);
	out.push_back({v, p});
}

vector<pair<int, pair<int, int> > > output;

void get_ans(int v, int p) {
	out.clear();
	dfs_out(v, p);
	out.pop_back();
	int cur = v;
	for (pair<int, int> a : out) {
		output.push_back({ p, {cur, a.first} });
		output.push_back({ a.first, {a.second, v} });
		cur = a.first;
	}
	output.push_back({ p, {cur, v} });
}

int main(){
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
#endif
	cin >> n;
	for (int i = 0; i < n - 1; ++i) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		g[a].push_back(b);
		g[b].push_back(a);
	}
	count(0);
	for (int to : g[c1])
		if (to != c2)
			get_ans(to, c1);
	if (c2 != -1)
		for (int to : g[c2])
			if (to != c1)
				get_ans(to, c2);
	cout << output.size() << '\n';
	for (int i = 0; i < output.size(); ++i)
		cout << output[i].first + 1 << " " << output[i].second.first + 1 << " " << output[i].second.second + 1 << '\n';

	return 0;
}

#include <bits/stdc++.h>

using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ll long long
const int N = 1e6+5;
vector<int>g[N],p,gg[N];
vector<vector<int> >ans;
int size[N],n,f[N]={0},size_p[N]={0},V[N];
map<pair<int,int>,int>m;
vector<int>tmp;
vector<pair<int,int> >tmp1;
int dfs(int u,int fa)
{
	size[u]=1;
	for(auto &v:g[u]){if(v==fa)continue;size[u]+=dfs(v,u);}
	return size[u];
}
void dfs1(int u,int fa)
{
	for(auto &v:g[u]){if(v==fa)continue;dfs1(v,u);}
	int ma=n-size[u];
	for(auto &v:g[u]){if(v==fa)continue;ma=max(ma,size[v]);}
	if(ma*2<=n)p.pb(u);
}
void dfs2(int u,int fa)
{
	for(auto &v:g[u]){if(v==fa||2*size[v]==n)continue;dfs2(v,u);}
	int ff=fa;
	if(fa!=-1&&n-size[u]>size[u])for(auto &v:g[u]){if(v==fa)continue;
		if(!V[u])V[u]=f[v];
		ans.pb({ff,u,f[v]});
		m[{ff,u}]=m[{u,ff}]=0;m[{ff,f[v]}]=m[{f[v],ff}]=1;
		ff=(V[v]==0?v:V[v]);
	}f[u]=u;
}
int dfs4(int u,int fa)
{
	int t;
	for(auto &v:g[u]){if(v==fa)continue;t=dfs4(v,u);}
	if((int)g[u].size()==1)return u;
	if(fa!=-1) ans.pb({fa,u,t});
	return t;
}
int dfs5(int u,int fa)
{
	int si=1;
	for(auto &v:g[u]){if(v==fa)continue;si+=dfs5(v,u);}
	if(n%2==0){if(si==n/2){tmp1.pb({fa,u});tmp1.pb({u,fa});}}
	else{if(si==n/2+1)tmp1.pb({u,-1});}
	return si;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].pb(v);g[v].pb(u);}
	dfs(1,-1);dfs1(1,-1);
	for(int i=1;i<=n;i++)for(auto &v:g[i])m[{i,v}]=1;

	for(auto &t:p)dfs(t,-1),dfs2(t,-1);
	//for(auto &t:ans)printf("%d %d %d\n",t[0],t[1],t[2] );
	for(int i=1;i<=n;i++)g[i].clear();
	for(auto &t:m)if(t.se){g[t.fi.fi].pb(t.fi.se);size_p[t.fi.se]++;}
	dfs(1,-1);
	for(int i=1;i<=n;i++)if(size_p[i]>2)tmp.pb(i);
	if((int)tmp.size()==0){int tt;
		for(int i=1;i<=n;i++)if(size_p[i]==1){tt=i;break;}
		dfs5(tt,-1);
	}else{tmp.clear();for(auto &t:p)tmp.pb(t);
		if((int)tmp.size()==1)for(auto &v:g[tmp[0]])tmp1.pb({v,tmp[0]});
		else{
			for(auto &v:g[tmp[0]])if(v!=tmp[1])tmp1.pb({v,tmp[0]});
			for(auto &v:g[tmp[1]])if(v!=tmp[0])tmp1.pb({v,tmp[1]});
		}
	}
	for(auto &t:tmp1)dfs4(t.fi,t.se);
	printf("%d\n",(int)ans.size() );
	for(auto &t:ans)printf("%d %d %d\n",t[0],t[1],t[2] );
	return 0;
}
/*
10
1 4
1 5
1 6
1 2
2 10
10 3
3 7
3 8
3 9
*/

#include <bits/stdc++.h>

using namespace std;

#define forn(i,n) for (int i = 0; i < int(n); i++)
#define ford(i,n) for (int i = int(n) - 1; i >= 0; i--)
#define fore(i,l,r) for (int i = int(l); i <= int(r); i++)
#define all(a) a.begin(), a.end()
#define sz(a) int(a.size())
#define mp make_pair
#define pb push_back
#define ft first
#define sc second
#define x first
#define y second

template<typename X> inline X abs(const X& a) { return a < 0 ? -a : a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

typedef long long li;
typedef long double ld;
typedef pair<int, int> pt;

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

const int N = 200 * 1000 + 5;
vector<int> g[N];
int n;

inline bool read() {
	scanf("%d", &n);
	forn (i, n - 1) {
		int a, b;
		scanf("%d%d", &a, &b);
		a--, b--;
		g[a].pb(b);
		g[b].pb(a);
	}
	return true;
}

bool used[N];

vector<pair<int, pt> > ans;

int tsz[N];

int calc(int v, int p) {
	tsz[v] = 1;
	for (int to : g[v]) {
		if (used[to] || to == p)
			continue;
		tsz[v] += calc(to, v);
	}
	return tsz[v];
}

int findc(int v, int p, int sz) {
	for (int to : g[v]) {
		if (used[to] || to == p)
			continue;
		if (tsz[to] * 2 > sz)
			return findc(to, v, sz);
	}
	return v;
}

int centroid(int v) {
	int sz = calc(v, -1);
	return findc(v, -1, sz);
}

int decomp(int v, bool split) {
	int c = centroid(v);
	if (split)
		c = v;
	used[c] = true;
	for (int to : g[c]) {
		if (used[to])
			continue;
		int ct = decomp(to, false);
		if (to != ct)
			ans.pb(mp(c, mp(to, ct)));
	}
	return c;
}

void removeEdge(int v, int u) {
	forn (i, sz(g[v]))
		if (g[v][i] == u)
			g[v].erase(g[v].begin() + i);
	forn (i, sz(g[u]))
		if (g[u][i] == v)
			g[u].erase(g[u].begin() + i);
}

bool usedBuild[N];

vector<int> gg[N];
vector<int> leaf;
int d[N];
int par[N];
bool ub[N];

vector<pair<int, pt> > ans2;

void dfs(int v, int p) {
	d[v] = 0;
	par[v] = p;
	ub[v] = true;
	for (int to : g[v])
		if (to != p) {
			dfs(to, v);
			d[v]++;
	}
	if (sz(g[v]) == 1)
		leaf.pb(v);
}

void addEdge(int a, int b) {
	gg[a].pb(b);
	gg[b].pb(a);
}

void printPath(int v, int p = -1) {
	cerr << v + 1 << ' ';
	int cnt = 0;
	for (int to : gg[v])
		if (to != p) {
			printPath(to, v);
			cnt++;
		}
	assert(cnt <= 1);
}

void build(int root) {
	memset(ub, false, sizeof ub);
	ub[root] = true;
	forn (i, n)
		gg[i].clear();
	for (int _to : g[root]) {
		leaf.clear();
		dfs(_to, root);
		int v = leaf.back();
		leaf.pop_back();
		ans2.pb(mp(root, mp(_to, v)));
		addEdge(root, v);
		while(par[v] != root) {
			int p = par[v];
			if (d[p] > 1) {
				d[p]--;
				int nxt = leaf.back();
				leaf.pop_back();
				ans2.pb(mp(v, mp(p, nxt)));
				addEdge(v, nxt);
				v = nxt;
			} else {
				addEdge(v, p);
				v = p;
			}
		}
	}
	forn (i, n)
		if (ub[i])
			g[i] = gg[i];
	//cerr << "PATH" << endl;
	//printPath(root);
	//cerr << endl;
}

inline void solve() {
	calc(0, -1);
	bool split = false;
	forn (i, n) {
		for (int to : g[i]) {
			if (tsz[to] * 2 == n && tsz[i] > tsz[to]) {
				removeEdge(i, to);
				split = true;
				build(i);
				build(to);
				decomp(i, split);
				decomp(to, split);
			}
		}
	}
	if (!split) {
		build(centroid(0));
		decomp(0, split);
	}
	reverse(all(ans));
	printf("%d\n", sz(ans) + sz(ans2));
	for (auto v : ans2) {
		printf("%d %d %d\n", v.x + 1, v.y.x + 1, v.y.y + 1);
	}
	for (auto v : ans) {
		printf("%d %d %d\n", v.x + 1, v.y.x + 1, v.y.y + 1);
	}
}

int main()
{
#ifdef _DEBUG
	assert(freopen("input.txt", "r", stdin));
	assert(freopen("output.txt", "w", stdout));
#endif

	cout << setprecision(25) << fixed;
	cerr << setprecision(10) << fixed;

	srand(int(time(NULL)));

	read();
	solve();

#ifdef _DEBUG
	cerr << "TIME: " << clock() << endl;
#endif

	return 0;
}

#include <bits/stdc++.h>

#define FOR(i,b,e) for(int i=(b); i <= (e); ++i)
#define FORD(i,b,e) for(int i=(b); i >= (e); --i)
#define REP(i,n) for(int i=0; i < (n); ++i)
#define SIZE(c) (int) (c).size()
#define ALL(c) (c).begin(), (c).end()
#define PB push_back
#define MP make_pair
#define ST first
#define ND second
#define FWD(i,a,b) for (int i=(a); i<(b); ++i)
#define BCK(i,a,b) for (int i=(a); i>(b); --i)
#define PI 3.14159265358979311600
#define pb push_back
#define mp make_pair
#define st first
#define nd second

using namespace std;

typedef long long ll;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;

typedef vector < int > VI;
typedef vector<ll> VL;

typedef long double K;

const int N = 200005;

int n, taken[N], sz[N];
vector<int> g[N];
set<int> s[N];
vector<int> centroids;
vector<tuple<int,int,int>> result;

void dfs(int v, int pr = -1) {
	sz[v] = 1;
	int mx = 0;
	for (auto& to : g[v]) if (to != pr) {
		dfs(to, v);
		sz[v] += sz[to];
		mx = max(mx, sz[to]);
	}
	mx = max(mx, n - sz[v]);
	if (2*mx <= n) {
		centroids.push_back(v);
		taken[v] = 1;
	}
}

void output(int a, int b, int c, bool change = true) {
	result.emplace_back(a+1, b+1, c+1);
	if (change) {
		s[a].erase(b);
		s[b].erase(a);
		s[a].insert(c);
		s[c].insert(a);
	}
}

pair<int,int> bamboo(int v, int pr) {
	vector<pair<int,int>> all;
	for (auto& to : g[v]) if (to != pr) {
		all.push_back(bamboo(to, v));
	}
	if (all.empty()) return {v, v};
	for (int i = 0; i < SIZE(all) - 1; ++i) {
		output(pr, v, all[i].second);
		pr = all[i].first;
	}
	return {all[0].second, all.back().second};
}

int solve(int v, int pr) {
	sz[v] = 1;
	int here;
	for (auto& to : s[v]) if (to != pr) {
		here = solve(to, v);
		sz[v] += sz[to];
	}
	if (sz[v] <= 2) return v;
	output(pr, v, here, false);
	return here;
}

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

	cin >> n;

	REP(i, n - 1) {
		int x, y;
		cin >> x >> y;
		--x; --y;
		g[x].push_back(y);
		g[y].push_back(x);
		s[x].insert(y);
		s[y].insert(x);
	}

	dfs(0);

	for (auto& v : centroids) {
		for (auto& ver : g[v]) {
			if (taken[ver]) continue;
			bamboo(ver, v);
		}
		for (auto& ver : s[v]) {
			solve(ver, v);
		}
	}

	cout << SIZE(result) << '\n';

	for (auto& item : result) {
		int a, b, c;
		tie(a, b, c) = item;
		cout << a << ' ' << b << ' ' << c << '\n';
	}

	return 0;
}

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <sstream>
#include <string>
#include <map>
#include <set>
#include <stdlib.h>
#include <cmath>
#include <math.h>
#include <fstream>
#include <bitset>
#include <queue>
#include <ctime>
#define int long long
using namespace std;
int INF = 1e18;
int maximum, n, ai, bi;
struct Vertex{int l; int r; int pr; int sz; int value; bool p;};
vector<Vertex> decart;
vector<vector<int> > data, ne, ans;
vector<pair<int, int> > edges;
vector<int> h, bases;
vector<bool> orient;
pair<int, int> SP = make_pair(-1, -1);
void update(int vertex){
    if (vertex == -1) return;
    int sz = 1;
    if (decart[vertex].l != -1){
        sz += decart[decart[vertex].l].sz;
    }
    if (decart[vertex].r != -1){
        sz += decart[decart[vertex].r].sz;
    }
    decart[vertex].sz = sz;
}
void push(int vertex){
    if (vertex == -1) return;
    if (!decart[vertex].p) return;
    decart[vertex].p = false;
    swap(decart[vertex].l, decart[vertex].r);
    if (decart[vertex].l != -1){
		decart[decart[vertex].l].p ^= 1;
    }
    if (decart[vertex].r != -1){
		decart[decart[vertex].r].p ^= 1;
    }
}
pair<int, int> split(int father, int number){
    if (father == -1) return SP;
    push(father);
    int l = 1;
    if (decart[father].l != -1){
        l += decart[decart[father].l].sz;
    }
    if (l <= number){
        pair<int, int> p = split(decart[father].r, number - l);
        decart[father].r = p.first;
        p.first = father;
        update(father);
        return p;
    }
    pair<int, int> p = split(decart[father].l, number);
    decart[father].l = p.second;
    p.second = father;
    update(father);
    return p;
}
int merg(int first, int second){
    push(first);
    push(second);
    if (first == -1) return second;
    if (second == -1) return first;
    if (decart[first].pr >= decart[second].pr){
        int v = merg(decart[first].r, second);
        decart[first].r = v;
        update(first);
        return first;
    }
    int v = merg(first, decart[second].l);
    decart[second].l = v;
    update(second);
    return second;
}
int dfs(int vertex, int last){
	int g = 1;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (last == to) continue;
        int num_e = ne[vertex][i];
        if (edges[num_e].first != vertex) orient[num_e] = false;
		g += dfs(to, vertex);
	}
	h[vertex] = g;
	return g;
}
int get_left(int vertex){
	push(vertex);
	if (decart[vertex].l == -1) return decart[vertex].value;
	return get_left(decart[vertex].l);
}
void form(int vertex, int e, int last){
	Vertex v = {-1, -1, rand(), 1, e, false};
	decart.push_back(v);
	int num = decart.size() - 1;
	int lastv;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (last == to) continue;
		lastv = i;
	}
    for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (last == to) continue;
		form(to, ne[vertex][i], vertex);
		if (i == lastv){
			num = merg(num, bases[to]);
			continue;
		}
		int b = bases[to];
		decart[b].p ^= 1;
        int ed = get_left(b);
        int so;
        if (orient[ed]) so = edges[ed].second;
        else so = edges[ed].first;
        vector<int> help;
        help.push_back(last);
        help.push_back(vertex);
        help.push_back(so);
        ans.push_back(help);
        if (edges[e].first == to){
			edges[e].first = so;
		}
		else edges[e].second = so;
		num = merg(num, b);
    }
    bases[vertex] = num;
}
void solve(int vertex, int sec){
	vector<int> sv;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (to == sec) continue;
		sv.push_back(to);
        form(data[vertex][i], ne[vertex][i], vertex);
	}
	if (sec != -1){
	for (int i=0; i < data[sec].size(); i++){
		int to = data[sec][i];
		if (to == vertex) continue;
		sv.push_back(to);
        form(data[sec][i], ne[sec][i], sec);
	}
	}
	for (int i=0; i < sv.size(); i++){
		int to = sv[i];
        int b = bases[to];
        int sz = decart[b].sz;
        if (sz <= 2) continue;
        pair<int, int> p = split(b, sz-1);
        pair<int, int> p1 = split(p.first, sz-2);
        int ov, ev;
        int N = decart[p.second].value;
        int V = decart[p1.second].value;
        if ((edges[N].first == edges[V].second) || (edges[N].second == edges[V].second)){
			ov = edges[V].second;
			ev = edges[V].first;
        }
        if ((edges[N].first == edges[V].first) || (edges[N].second == edges[V].first)){
			ev = edges[V].second;
			ov = edges[V].first;
        }
        b = p1.first;
        while (b != -1){
            pair<int, int> p = split(b, decart[b].sz - 1);
			b = p.first;
			int W = decart[p.second].value;
			if (edges[W].first == ev){
                vector<int> help;
                help.push_back(edges[W].second);
                help.push_back(edges[W].first);
                help.push_back(ov);
                ans.push_back(help);
                ev = edges[W].second;
			}
			else{
				vector<int> help;
                help.push_back(edges[W].first);
                help.push_back(edges[W].second);
                help.push_back(ov);
                ans.push_back(help);
                ev = edges[W].first;
			}
        }
	}
}
void get_centroid(int vertex){
	maximum = 0;
	int wh;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		int res = dfs(to, vertex);
		if (res > maximum){
			maximum = res;
			wh = to;
		}
	}
	int ll = vertex;
	while (maximum*2 > n){
		int mm = 0, vv;
		for (int i=0; i < data[wh].size(); i++){
			int to = data[wh][i];
			if (to == ll) continue;
			if (h[to] > mm){
				mm = h[to];
				vv = to;
			}
		}
        maximum = mm;
        ll = wh;
        wh = vv;
	}
	dfs(ll, -1);
	int se = -1;
	for (int i=0; i < data[ll].size(); i++){
		int to = data[ll][i];
        if (2 * h[to] >= n){
			se = to;
        }
	}
    solve(ll, se);
}
int32_t main(){
    cin >> n;
    for (int i=0; i < n; i++){
		vector<int> help, hh;
		h.push_back(0);
		ne.push_back(hh);
		bases.push_back(-1);
		orient.push_back(true);
		data.push_back(help);
    }
    for (int i=0; i < n-1; i++){
		cin >> ai >> bi;
		data[ai-1].push_back(bi-1);
		data[bi-1].push_back(ai-1);
		ne[ai-1].push_back(i);
		ne[bi-1].push_back(i);
		edges.push_back(make_pair(ai-1, bi-1));
    }
    get_centroid(0);
    cout << ans.size() << endl;
    for (int i=0; i < ans.size(); i++){
		cout << ans[i][0] + 1 << " " << ans[i][1] + 1 << " " << ans[i][2] + 1 << endl;
    }
	return 0;
}

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define fio ios_base::sync_with_stdio(false)
#define MOD 1000000007
#define INF 1000000000
#define INFLL 1000000000000000000ll
#define stlfor(a, b) for(auto a=b.begin(); a!=b.end(); a++)
#define rstlfor(a, b) for(auto a=b.rbegin(); a!=b.rend(); a++)
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
#define long int64_t
using namespace std;
using namespace __gnu_pbds;
typedef pair<int, int> pii;
typedef priority_queue<pii, vector<pii>, greater<pii>> min_pq;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> OST;

const int N = 200001;

struct S
{
    int x, y1, y2;
};

int cp[N], w[N], croot;
vector<int> tr[N];
bool cmark[N];
vector<S> ans;

int init_dfs(int node, int par)
{
    w[node] = 1;
    for(auto &it : tr[node])
        if(it != par && !cmark[it])
            w[node] += init_dfs(it, node);
    return w[node];
}

int find_centroid(int node, int par, int tw)
{
    int mnode, mw = 0;
    for(auto &it : tr[node])
    {
        if(it != par && !cmark[it])
        {
            if(mw < w[it])
            {
                mw = w[it];
                mnode = it;
            }
        }
    }
    if(mw <= tw)
        return node;
    return find_centroid(mnode, node, tw);
}

void build_ctr()
{
    int t = init_dfs(1, 0);
    croot = find_centroid(1, 0, t >> 1);
    cmark[croot] = true;
    queue<pii> q;
    q.push(mp(croot, t));
    while(!q.empty())
    {
        pii f = q.front();
        int node = f.ff;
        q.pop();
        for(auto &it : tr[node])
        {
            if(!cmark[it])
            {
                t = init_dfs(it, node);
                int c = find_centroid(it, node, t >> 1);
                cp[c] = node;
                cmark[c] = true;
                q.push(mp(c, t));
                if(f.ss - t > t)
                    ans.pb({node, it, c});
            }
        }
    }
}

int main()
{
    fio;
    int n;
    cin >> n;
    for(int i=1; i<n; i++)
    {
        int a, b;
        cin >> a >> b;
        tr[a].pb(b);
        tr[b].pb(a);
    }
    build_ctr();
    cout << ans.size() << endl;
    for(auto &it : ans)
        cout << it.x << ' ' << it.y1 << ' ' << it.y2 << endl;
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define eb emplace_back
#define ll long long
#define pii pair < int, int >
#define fr first
#define sc second
#define mk make_pair
#define sz(s) (int)s.size()
#define all(s) s.begin(), s.end()
#define ok puts("ok");
#define whatis(x) cerr << #x << " = " << x << endl;

const int N = (int)2e5 + 7;
const int inf = (int)1e9 + 7;

int n;
vector < int > gr[N];
int deg[N];
vector < pair < pii, int > > ans;
bool is[N], p[N];
int V;

void dfs(int v, int pr) {
  p[v] = pr;
  if (pr == V) {
    is[v] = 1;
  }
  if (!is[v]) {
    ans.pb(mk(mk(v, pr), V));
  }
  for (int to : gr[v]) {
    if (to == pr) continue;
    dfs(to, v);
  }
}

main() {
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d %d", &u, &v);
    gr[u].pb(v);
    gr[v].pb(u);
    deg[u]++;
    deg[v]++;
  }
  int mx = 0;
  for (int i = 1; i <= n; i++) {
    if (deg[i] > mx) {
      V = i;
      mx = deg[i];
    }
  }
  assert(V != -1);
  is[V] = 1;
  dfs(V, 0);
  cout << sz(ans) << "\n";
  for (int i = 0; i < sz(ans); i++) {
    auto to = ans[i];
    printf("%d %d %d\n", to.fr.fr, to.fr.sc, to.sc);
  }
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define pb push_back
#define mp make_pair

int n;
set<int> g[200010];
queue<pii> q[200010];
char c[200010];
set<int> centers;
struct tup{
    int x, y, yy, p;
    tup(int x, int y, int yy): x(x), y(y), yy(yy) {}
};
vector<tup> ans;
vector<int> cur;
vector<int> tmp;

int mxd, leaf;
int r;
int st, ed;

void dfs1(int v, int p, int d){
    if(d > mxd){
        mxd = d;
        leaf = v;
    }
    for(auto to: g[v]){
        if(to != p) dfs1(to, v, d + 1);
    }
}

void dfs2(int v, int p){
    tmp.pb(v);
    if(v == ed){
        int m = tmp.size();
        if(m % 2 == 1){
            centers.insert(tmp[m / 2]);
        }
        else{
            centers.insert(tmp[m / 2]);
            centers.insert(tmp[m / 2 - 1]);
        }
        for(auto u: centers) c[u] = true;
    }
    for(auto to: g[v]){
        if(to != p) dfs2(to, v);
    }
    tmp.pop_back();
}

void find_centers(){
    dfs1(0, 0, 0);
    st = leaf;
    mxd = 0;
    dfs1(st, st, 0);
    ed = leaf;
    dfs2(st, st);
}

pii solve(int v, int p){
    for(auto to: g[v]){
        if(to != p){
            q[v].push(solve(to, v));
        }
    }
    while(q[v].size() > 1){
        ans.pb(tup(p, v, q[v].front().first));
        p = q[v].front().second;
        q[v].pop();
    }
    return (q[v].empty()) ? mp(v, v) : mp(q[v].front().first, p);
}

void solve2(int v, int p){
    cur.pb(v);
    for(auto to: g[v]){
        if(to != p) solve2(to, v);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n;
    for(int i = 0; i < n - 1; i++){
        int from, to;
        cin >> from >> to;
        g[from - 1].insert(to - 1);
        g[to - 1].insert(from - 1);
    }
    find_centers();
    for(auto u: centers){
        for(auto v: g[u]){
            if(c[v]) continue;
            solve(v, u);
        }
    }
    for(tup u: ans){
        g[u.x].erase(u.y);
        g[u.y].erase(u.x);
        g[u.x].insert(u.yy);
        g[u.yy].insert(u.x);
    }
    for(auto u: centers){
        for(auto to: g[u]){
            if(c[to]) continue;
            cur.clear();
            cur.pb(u);
            solve2(to, u);
            cur.pop_back();
            int last = cur.back();
            cur.pop_back();
            for(int i = cur.size() - 1; i >= 1; i--){
                ans.pb(tup(cur[i - 1], cur[i], last));
            }
        }
    }
    assert(ans.size() <= 2 * n);
    cout << ans.size() << endl;
    for(auto u: ans){
        cout << u.x + 1 << ' ' << u.y + 1 << ' ' << u.yy + 1 << endl;
    }
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define eb emplace_back
#define ll long long
#define pii pair < int, int >
#define fr first
#define sc second
#define mk make_pair
#define sz(s) (int)s.size()
#define all(s) s.begin(), s.end()
#define ok puts("ok");
#define whatis(x) cerr << #x << " = " << x << endl;

const int N = (int)2e5 + 7;
const int inf = (int)1e9 + 7;

int n;
vector < int > gr[N];
int deg[N], sz[N];
int centroidpr[N], h[N];
bool cen[N];
int siz;
vector < pair < pii, int > > ans;

void getsz(int v, int pr) {
  sz[v] = 1;
  for (int to : gr[v]) {
    if (to == pr || cen[to]) continue;
    getsz(to, v);
    sz[v] += sz[to];
  }
}

int findcentroid(int v, int pr) {
  for (int to : gr[v]) {
    if (to == pr || cen[to]) continue;
    if (sz[to] * 2 >= siz) {
      return findcentroid(to, v);
    }
  }
  return v;
}

void centroid(int v, int pr) {
  getsz(v, pr);
  siz = sz[v];
  int centre = findcentroid(v, pr);
  centroidpr[centre] = pr;
  h[centre] = h[pr] + 1;
  cen[centre] = 1;
  if (pr != 0) {
    if (v != centre)
      ans.pb(mk(mk(pr, v), centre));
  }
  for (int to : gr[centre]) {
    if (to == pr || cen[to]) continue;
    centroid(to, centre);
  }
}

main() {
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d %d", &u, &v);
    gr[u].pb(v);
    gr[v].pb(u);
  }
  centroid(1, 0);
  cout << min(sz(ans), 2 * n) << "\n";
  for (int i = 0; i < min(sz(ans), 2 * n); i++) {
    auto to = ans[i];
    printf("%d %d %d\n", to.fr.fr, to.fr.sc, to.sc);
  }
}

#include <bits/stdc++.h>

using namespace std;

typedef pair <int,int> pii;

#define L first
#define R second

const int maxn = 2e5 + 100;
vector <pair<int,pii> > ans;
vector <int> adj[maxn], ver;
bool mark[maxn];
int sub[maxn];

bool ic(int v,int u) {
	int idx = lower_bound(adj[v].begin(), adj[v].end(), u) - adj[v].begin();
	if (idx != adj[v].size() && adj[v][idx] == u)
		return true;
	return false;
}

void dfs_do(int v,int par = -1) {
	sub[v] = 1;
	ver.push_back(v);
	for (auto u : adj[v])
		if (u != par && !mark[u]) {
			dfs_do(u, v);
			sub[v] += sub[u];
		}
}

int solve(int sr) {
	ver.clear();
	dfs_do(sr);
	int cen = -1;
	for (auto v : ver) {
		bool okay = true;
		for (auto u : adj[v])
			if (sub[v] > sub[u] && sub[u] * 2 > ver.size())
				okay = false;
		if (sub[v] * 2 < ver.size())
			okay = false;
		if (okay)
			cen = v;
	}
	mark[cen] = true;
	for (auto v : adj[cen])
		if (!mark[v]) {
			int cv = solve(v);
			if (v != cv)
				ans.push_back({cen, {v, cv}});
		}
	return cen;
}

int main() {
	ios_base::sync_with_stdio(false);
	int n;
	cin >> n;
	for (int i = 1; i < n; i++) {
		int v, u;
		cin >> v >> u;
		v--, u--;
		adj[v].push_back(u);
		adj[u].push_back(v);
	}
	for (int i = 0; i < n; i++)
		sort (adj[i].begin(), adj[i].end());
	solve(0);
	cout << ans.size() << '\n';
	for (int i = ans.size() - 1; i >= 0; i--)
		cout << ans[i].L + 1 << ' ' << ans[i].R.L + 1 << ' ' << ans[i].R.R + 1 << '\n';
	return 0;
}

// .... .... .....!
// ...... ......!
// .... ....... ..... ..!
// ...... ... ... .... ... .... .....!
// ... .. ... .... ...?
// ....... .. .... .. ...., ....... ..!

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

#define rep(i, n) for (int i = 0, i##__n = (int)(n); i < i##__n; ++i)
#define fer(i, a, b) for (int i = (int)(a), i##__b = (int)(b); i < i##__b; ++i)
#define rof(i, b, a) for (int i = (int)(b), i##__a = (int)(a); i-- > i##__a; )
#define sz(x) (int((x).size()))
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define X first
#define Y second
//#define endl '\n'

template<class P, class Q> inline void smin(P &a, Q b) { if (b < a) a = b; }
template<class P, class Q> inline void smax(P &a, Q b) { if (a < b) a = b; }

typedef long long ll;
typedef pair<int, int> pii;

////////////////////////////////////////////////////////////////////////////////

const int maxn = 200000 + 100;

int n;
vector<int> adj[maxn];
bool mark[maxn];
int sub_size[maxn];

int get_size(int u, int par = -1) {
	int ret = 1;
	for(int v: adj[u]) if(v != par && !mark[v]) ret += get_size(v, u);
	return sub_size[u] = ret;
}

int find_center(int u, int comp_size, int par = -1) {
	int max_sub = comp_size - sub_size[u];
	for(int v: adj[u]) if(v != par && !mark[v]) {
		int tmp = find_center(v, comp_size, u);
		if(tmp != -1) return tmp;
		smax(max_sub, sub_size[v]);
	}
	if(max_sub <= comp_size / 2) return u;
	return -1;
}

vector<int> vx, vy, vz;

int solve(int u) {
	int comp_size = get_size(u);
	u = find_center(u, comp_size);

	mark[u] = true;
	for(int v: adj[u]) if(!mark[v]) {
		int c = solve(v);
		if(c != v) vx.pb(u), vy.pb(v), vz.pb(c);
	}

	return u;
}

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

	cin >> n;
	rep(i, n-1) {
		int u, v; cin >> u >> v; u--, v--;
		adj[u].pb(v), adj[v].pb(u);
	}

	solve(0);

	cout << sz(vx) << endl;
	rep(i, sz(vx)) cout << vx[i] + 1 << ' ' << vy[i] + 1 << ' ' << vz[i] + 1 << endl;

	return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

const int INF = (int) 1e9 + 123;
const ll LINF = (ll) 1e18 + 123;
const ld EPS = (ld) 1e-12;
const ll MOD = (ll) 1e9 + 7;

#define sz(x) (int) (x).size()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define lb(s, t, x) (int) (lower_bound(s, t, x) - s)
#define ub(s, t, x) (int) (upper_bound(s, t, x) - s)
#define rep(i, f, t) for (auto i = f; i < t; i++)
#define per(i, f, t) for (auto i = f; i >= t; i--)

ll power(ll x, ll y, ll mod = MOD) {
    if (y == 0) {
        return 1;
    }
    if (y & 1) {
        return power(x, y - 1, mod) * x % mod;
    } else {
        ll tmp = power(x, y / 2, mod);
        return tmp * tmp % mod;
    }
}

inline void add(ll &x, ll y, ll mod = MOD) {
    x += y;
    if (x >= mod) x -= mod;
    if (x < 0) x += mod;
}

inline ll sum(ll x, ll y, ll mod = MOD) {
    add(x, y, mod);
    return x;
}

inline ll mult(ll x, ll y, ll mod = MOD) {
    return (x * y) % mod;
}

inline ll div(ll x, ll y, ll mod) {
    return x * power(y, mod - 2, mod);
}

template<typename A, typename B> inline bool mini(A &x, const B &y) {
    if (y < x) {
        x = y;
        return true;
    }
    return false;
}

template<typename A, typename B> inline bool maxi(A &x, const B &y) {
    if (y > x) {
        x = y;
        return true;
    }
    return false;
}

template<typename T> inline void read(T first, T last) {
    while (first != last) {
        cin >> *(first++);
    }
}

template<typename T> inline void print(T first, T last) {
    while (first != last) {
        cout << *(first++) << " ";
    }
    cout << "\n";
}

void run();

#define TASK ""

int main() {
#ifdef LOCAL
    if (strlen(TASK) > 0) {
        cerr << "Reminder: you are using file i/o, filename: " TASK "!" << endl << endl;
    }
#endif
#ifndef LOCAL
    if (strlen(TASK)) {
        freopen(TASK ".in", "r", stdin);
        freopen(TASK ".out", "w", stdout);
    }
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif
    cout << fixed << setprecision(12);
    run();
    return 0;
}

// == SOLUTION == //

const int N = (int) 2e5 + 123;

struct Q {
    int x, y1, y2;
};

int n;
vector<pair<int, int>> g[N];
vector<Q> res;
bool vis[N], used[N];
int cnt[N];

void calc_cnt(int v, int p = -1) {
    cnt[v] = 1;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || u == p || used[e.second]) continue;
        calc_cnt(u, v);
        cnt[v] += cnt[u];
    }
}

int dfs(int v);

pair<bool, int> centroid_edge(int v, int all, int p = -1) {
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || u == p || used[e.second]) continue;
        auto tmp = centroid_edge(u, all, v);
        if (tmp.first) return tmp;
        if (2 * cnt[u] == all) {
            used[e.second] = 1;
            dfs(v);
            dfs(u);
            return {1, v};
        }
    }
    return {0, -1};
}

void find_centroid(int v, int all, int &x, int p = -1) {
    bool ok = 1;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || used[e.second]) continue;
        ok &= 2 * (u != p ? cnt[u] : all - cnt[v]) < all;
        if (u == p) continue;
        find_centroid(u, all, x, v);
    }
    if (ok) {
        assert(x == -1);
        x = v;
    }
}

int dfs(int v) {
    calc_cnt(v);
    auto tmp = centroid_edge(v, cnt[v]);
    if (tmp.first) {
        return tmp.second;
    }

    int centroid = -1;
    find_centroid(v, cnt[v], centroid);
    assert(centroid != -1);
    v = centroid;
    vis[v] = 1;
    vector<Q> cur;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || used[e.second]) continue;
        int t = dfs(u);
        if (1) cur.push_back({v, u, t});
    }
    for (Q &q : cur) {
        res.pb(q);
    }
    return v;
}

void massert(bool x) {
    if (!x) {
        cerr << "bad" << endl;
    }
    #ifndef LOCAL
    assert(x);
    #endif
}

void run() {
    cin >> n;
    rep(i, 0, n - 1) {
        int u, v;
        cin >> u >> v;
        g[u].pb({v, i});
        g[v].pb({u, i});
    }

    dfs(1);

    cout << sz(res) << "\n";
    memset(vis, 0, sizeof vis);
    calc_cnt(1);
    reverse(all(res));
    for (Q &q : res) {
        if (cnt[q.x] < cnt[q.y1]) {
            //massert(cnt[q.x] > n - cnt[q.x]);
        } else {
            //massert(n - cnt[q.y1] > cnt[q.y1]);
        }
        cout << q.x << " " << q.y1 << " " << q.y2 << "\n";
    }
}

#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
int N, M;
vector <int> G[200005];
int Sz[200005], Size[200005];
int sum, cnt;
bool Blocked[200005];
struct Solution{
int x, y, y2;
} S[200005];
bool first;
void Read()
{
    scanf("%d", &N);
    for(int i = 2; i <= N; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
}

void DFS(int node, int father)
{
    Sz[node] = 1;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        DFS(neighb, node);
        Sz[node] += Sz[neighb];
    }
}

int findCentroid(int node, int father, int size)
{
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        if(Sz[neighb] > size / 2)
            return findCentroid(neighb, node, size);
    }
    return node;
}

int centroidDecompose(int root)
{
    DFS(root, 0);
    int center = findCentroid(root, 0, Sz[root]);
    Blocked[center] = 1;
    int sz = Sz[root];
    bool ok = 0;
    if(first == 0)
    {
        for(int i = 1; i <= N; i++)
        Size[i] = Sz[i];
        first = 1;
        ok = 1;
    }

    int node = center;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(Blocked[neighb] == 1)
            continue;
        int n = centroidDecompose(neighb);
        if(n == neighb || (ok == 1 && Size[neighb] == N - Size[neighb]))
            continue;
        ++cnt;
        S[cnt].x = center;
        S[cnt].y = neighb;
        S[cnt].y2 = n;
    }
    return center;
}
int main()
{
    Read();
    centroidDecompose(1);
    printf("%d\n", cnt);
    for(int i = 1; i <= cnt; i++)
    {
        printf("%d %d %d\n", S[i].x, S[i].y, S[i].y2);
    }
    return 0;
}

// E
#include <bits/stdc++.h>

#define SQ(a) (a)*(a)

#define F0R(i, a) for(int i = 0; i < (a); i++)
#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define R0F(i, a) for(int i = (a) - 1; i >= 0; i--)
#define ROF(i, a, b) for(int i = (b) - 1; i >= (a); i--)

#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define UB upper_bound
#define LB lower_bound
#define X real()
#define Y imag()
#define MAXN 200000

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef complex<ll> point;

int n;
bool isCentroid[MAXN];
vi connections[MAXN];
vector<tuple<int, int, int>> transformations;

int sizeOfTree(int node, int par) {
    int total = 1;
    for(const int conn : connections[node]) {
        if(conn != par && !isCentroid[conn]) total += sizeOfTree(conn, node);
    }
    return total;
}

int centroidDecompose(int node) {
    vector<pii> childrenSizes;
    int total = 1;
    for(const int conn : connections[node]) {
        if(!isCentroid[conn]) {
            childrenSizes.PB(MP(sizeOfTree(conn, node), conn));
            total+=childrenSizes[childrenSizes.size() - 1].F;
        }
    }
    for(const pii sizeOfChild : childrenSizes) {
        if(sizeOfChild.F > total / 2) return centroidDecompose(sizeOfChild.S);
    }
    isCentroid[node] = true;
    for(const pii sizeOfChild : childrenSizes) {
        int centroid = centroidDecompose(sizeOfChild.S);
        if(sizeOfChild.F <= total - sizeOfChild.F && centroid != sizeOfChild.S) {
            transformations.PB(MT(node, sizeOfChild.S, centroid));
        }
    }
    return node;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    F0R(i, n - 1) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        connections[a].PB(b), connections[b].PB(a);
    }
    centroidDecompose(0);
    cout << transformations.size() << "\n";
    for(const tuple<int, int, int> t: transformations) cout << get<0>(t) + 1 << " " << get<1>(t) + 1 << " " << get<2>(t) + 1 << "\n";
    return 0;
}

///****In the name of ALLAH, most Gracious, most Compassionate****//

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

typedef long long ll;
typedef pair <int, int> pii;

#define ALL(a) a.begin(), a.end()
#define FastIO ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define IN freopen("input.txt","r+",stdin)
#define OUT freopen("output.txt","w+",stdout)

#define DBG(a) cerr<< "line "<<__LINE__ <<" : "<< #a <<" --> "<<(a)<<endl
#define NL cout<<endl

template < class T1,class T2>
ostream &operator <<(ostream &os,const pair < T1,T2 > &p)
{
    os<<"{"<<p.first<<","<<p.second<<"}";
    return os;
}

const int N=3e5+5;
const int oo=1e9+7;

set<int > g[N];
int sz[N];

vector< tuple < int  , int  , int > > ans;

int dfs_sz(int u,int  p )
{
    sz[u] = 1;
    for(int v: g[u])
        if(v!=p)
            sz[u]+=dfs_sz(v,u);
    return sz[u];
}
int find_centroid(int u,int  p ,int size)
{
    for(int v: g[u])
        if(v!=p and sz[v] > size / 2)
            return find_centroid(v,u,size );
    return u;
}

int make_centroid_tree(int u)
{
    int size = dfs_sz(u,u);
    u= find_centroid(u,u,size);
    return u;
}

int find_leaf(int u , int p = -1)
{
    for(int v: g[u])
        if(v!=p)
            return find_leaf(v);
    return u;
}

vector<int > chain;

void make_chain(int u,int p ,int &uu,int &vv)
{
    for(int v: g[u])
        if(v!=p)
            make_chain(v,u,uu,vv);
    chain.push_back(u);
    if(u!=vv)
    ans.push_back(make_tuple(uu,vv,u));
    uu=u,vv = p;
}

void make_star(int u)
{
    int n =chain.size();
    for(int i=n-4;i>=0;i--)
    {
        ans.push_back(make_tuple(chain[i] , chain[i+1] , chain[n-2]));
    }
    if(n>=3)
        ans.push_back(make_tuple(u,chain.front() , chain[n - 2]));
}

int32_t main()
{
    FastIO;
    int n;
    cin>>n;
    for(int i=1;i<=n-1;i++)
    {
        int u,v;
        cin>>u>>v;
        g[u].insert(v);
        g[v].insert(u);
    }
    int centroid = make_centroid_tree(1);

    for(int v: g[centroid])
    {
        g[v].erase(centroid);
        chain.clear();
        int uu = centroid , vv = v;
        make_chain(v,centroid , uu,vv);
        make_star(centroid);

//        DBG(&chain);
//        for(int u: chain) cout<<u<<" "; NL;
    }

    cout<<ans.size()<<"\n";
    for(auto i: ans)
    {
        cout<<get<0>(i)<<" ";
        cout<<get<1>(i)<<" ";
        cout<<get<2>(i)<<"\n";
    }
}

#pragma comment(linker, "/STACK:204800000,204800000")
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
#include <functional>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <sstream>
#include <unordered_set>
#include <unordered_map>
#include <sstream>
#include <set>
#include <cassert>
using namespace std;

ifstream in("C:\\input.txt");
//istream& in = cin;
struct Node{
	int x, y1, y2;
	Node(int a, int b, int c){
		x = a;
		y1 = b;
		y2 = c;
	}
};

#define pii pair<int,int>
#define mp make_pair
#define pb push_back
typedef long long LL;
#define MMAX ((int)2e5+10)
vector<Node> ans;
vector<int> edge[MMAX];
int dfs(int p,int f){
	if (edge[p].size() == 1){
		return p;
	}
	int ret;
	for (int son : edge[p]){
		if (son == f)
			continue;
		ret = dfs(son, p);
		ans.push_back(Node(p, son, ret));
	}
	return ret;
}

int n;
vector<int> vi[MMAX];

int pre_dfs(int p, int f, bool root){
	if (vi[p].size() == 1){
	//	edge[p].pb(f);
	//	edge[f].pb(p);
		return p;
	}
	vector<pii> leaf;
	for (int son : vi[p]){
		if (son == f)
			continue;
		leaf.pb(mp(pre_dfs(son, p, 0),son));
	}

	if (root){
		for (int i = 0; i < leaf.size(); ++i){
			edge[vi[p][i]].push_back(p);
			edge[p].push_back(vi[p][i]);

		}
		return -1;
	}
	else{

		if (p == 5){
			int t = 0;
		}

		if (leaf.size() == 1){

			edge[p].push_back(leaf[0].second);
			edge[leaf[0].second].push_back(p);
			return leaf[0].first;
		}
		else{

			ans.push_back(Node(f, p, leaf.back().first));
			int nowf = leaf.back().second;
			int nowp = p;
			for (int i = leaf.size() - 2; i >= 0; --i){
				ans.push_back(Node(nowf, nowp, leaf[i].first));

				edge[leaf[i].first].push_back(nowf);
				edge[nowf].push_back(leaf[i].first);
				nowf = leaf[i].second;
				nowp = p;

			}
			edge[p].push_back(nowf);
			edge[nowf].push_back(p);
		}
		return p;
	}
}

void input(){
	in >> n;
	for (int i = 1; i < n; ++i){
		int a, b;
		in >> a >> b;
		vi[a].pb(b);
		vi[b].pb(a);
	}
}
int roota, rootb;
int get_root(int p,int f){
	int size = 1;
	for (int son : vi[p]){
		if (son == f)
			continue;
		size += get_root(son, p);
	}
	if (size == n / 2){
		if (size * 2 == n){
			roota = p;
			rootb = f;
		}
		else{
			roota = f;
		}
	}
	return size;
}

int main(){

	int TEST_CASE = 1;
	//in >> TEST_CASE;
	while (TEST_CASE-- > 0){
		input();
		if (n <= 3){
			cout << 0 << endl;
			continue;
		}
		roota = rootb = -1;

		get_root(1, -1);

		pre_dfs(roota, rootb, 1);
		if (rootb != -1){
			pre_dfs(rootb, roota, 1);
		}
		int num = 0;
		for (int i = 1; i <= n; ++i){
			num += edge[i].size();
		}
		if (n%2==1)
			assert(num / 2 == n - 1);
		else{
		//	assert(num / 2 == n - 2);
		}
		dfs(roota, -1);
		if (rootb != -1){
			dfs(rootb, -1);
		}

		printf("%d\n", ans.size());
		for (Node& p : ans){
			printf("%d %d %d\n", p.x, p.y1, p.y2);
		}

	}

	return 0;
}

#pragma region Macros
#pragma GCC optimize("O3")

#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i,a,b) for(ll i=a;i<=b;++i)
#define rep(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i>=b;--i)
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vec vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1,_2,name,...) name
#define vv(a,b) vector<vector<int>>(a,vector<int>(b))
#define vv2(a,b,c) vector<vector<int>>(a,vector<int>(b,c))
#define vvl(a,b) vector<vector<ll>>(a,vector<ll>(b))
#define vvl2(a,b,c) vector<vector<ll>>(a,vector<ll>(b,c))
#define vvv(a,b,c) vector<vv(b,c)>(a)
#define vvv2(a,b,c,d) vector<vv(b,c,d)>(a)
#define vvvl(a,b,c) vector<vvl(b,c)>(a)
#define vvvl2(a,b,c,d) vector<vvl(b,c,d)>(a)
#define fi first
#define se second
#define all(c) begin(c),end(c)
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define lb(c,x) distance((c).begin(),lower_bound(all(c),(x)))
#define ub(c,x) distance((c).begin(),upper_bound(all(c),(x)))
using namespace std;
template<class T> using pq = priority_queue<T>;
template<class T> using pqg = priority_queue<T,vector<T>,greater<T>>;
#define INT(...) int __VA_ARGS__;IN(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;IN(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__;IN(__VA_ARGS__)
#define STR(...) string __VA_ARGS__;IN(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__;IN(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__;IN(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__;IN(__VA_ARGS__)
#define VEC(type,name,size) vector<type> name(size);IN(name)
#define VV(type,name,h,w) vector<vector<type>>name(h,vector<type>(w));IN(name)
int scan(){ return getchar(); }
void scan(int& a){ cin>>a; }
void scan(long long& a){ cin>>a; }
void scan(char &a){cin>>a;}
void scan(double &a){ cin>>a; }
void scan(long double& a){ cin>>a; }
void scan(char a[]){ scanf("%s", a); }
void scan(string& a){ cin >> a; }
template<class T> void scan(vector<T>&);
template<class T, size_t size> void scan(array<T, size>&);
template<class T, class L> void scan(pair<T, L>&);
template<class T, size_t size> void scan(T(&)[size]);
template<class T> void scan(vector<T>& a){ for(auto& i : a) scan(i); }
template<class T> void scan(deque<T>& a){ for(auto& i : a) scan(i); }
template<class T, size_t size> void scan(array<T, size>& a){ for(auto& i : a) scan(i); }
template<class T, class L> void scan(pair<T, L>& p){ scan(p.first); scan(p.second); }
template<class T, size_t size> void scan(T (&a)[size]){ for(auto& i : a) scan(i); }
template<class T> void scan(T& a){ cin >> a; }
void IN(){}
template <class Head, class... Tail> void IN(Head& head, Tail&... tail){ scan(head); IN(tail...); }
string stin() {string s;cin>>s;return s;}
template<class T> inline bool chmax(T& a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T> inline bool chmin(T& a,T b){if(a>b){a=b;return 1;}return 0;}
vi iota(int n){vi a(n);iota(all(a),0);return a;}
template<class T> void UNIQUE(vector<T> &x){sort(all(x));x.erase(unique(all(x)),x.end());}
int in() {int x;cin>>x;return x;}
ll lin() {unsigned long long x;cin>>x;return x;}
void print(){putchar(' ');}
void print(bool a){cout<<a;}
void print(int a){cout<<a;}
void print(long long a){cout<<a;}
void print(char a){cout<<a;}
void print(string &a){cout<<a;}
void print(double a){cout<<a;}
template<class T> void print(const vector<T>&);
template<class T, size_t size> void print(const array<T, size>&);
template<class T, class L> void print(const pair<T, L>& p);
template<class T, size_t size> void print(const T (&)[size]);
template<class T> void print(const vector<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } cout<<endl;}
template<class T> void print(const deque<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } }
template<class T, size_t size> void print(const array<T, size>& a){ print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } }
template<class T, class L> void print(const pair<T, L>& p){ cout<<'(';print(p.first); cout<<","; print(p.second);cout<<')'; }
template<class T, size_t size> void print(const T (&a)[size]){ print(a[0]); for(auto i = a; ++i != end(a); ){ cout<<" "; print(*i); } }
template<class T> void print(const T& a){ cout << a; }
int out(){ putchar('\n'); return 0; }
template<class T> int out(const T& t){ print(t); putchar('\n'); return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; }
ll gcd(ll a, ll b){ while(b){ ll c = b; b = a % b; a = c; } return a; }
ll lcm(ll a, ll b){ if(!a || !b) return 0; return a * b / gcd(a, b); }
vector<pll> factor(ll x){ vector<pll> ans; for(ll i = 2; i * i <= x; i++) if(x % i == 0){ ans.push_back({i, 1}); while((x /= i) % i == 0) ans.back().second++; } if(x != 1) ans.push_back({x, 1}); return ans; }
vector<int> divisor(int x){ vector<int> ans; for(int i=1;i*i<=x;i++)if(x%i==0){ans.pb(i);if(i*i!=x)ans.pb(x/i);} return ans;}
int popcount(ll x){return __builtin_popcountll(x);}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int n){return uniform_int_distribution<int>(0, n)(rng);}
#define endl '\n'

#ifdef _LOCAL
    #undef endl
    #define debug(x) cout<<#x<<": ";print(x);cout<<endl;
    void err(){}
    template<class T> void err(const T& t){ print(t);  cout<<" ";}
    template<class Head, class... Tail> void err(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); }
#else
    #define debug(x)
    template<class... T> void err(const T&...){}
#endif
#pragma endregion

template< typename T >
struct edge{
    int from, to;
    T cost;
    edge(int to,T cost) : from(-1), to(to), cost(cost){}
    edge(int from,int to,T cost) : from(from), to(to), cost(cost){}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const{ return to;}
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedTree = vector< Edges<T>>;
using tree = vector< vector<int> >;
using UnWeightedGraph = tree;
tree make(int n,int offset = 1){
    tree res(n);
    for(int i = 0;i < n-1; i++){
        int a,b; cin >> a >> b;
        a -= offset,b -= offset;
        res[a].emplace_back(b);
        res[b].emplace_back(a);
    }
    return res;
}
template< typename T >
WeightedTree<T> make2(int n, int offset = 1){
    WeightedTree<T> res(n);
    for(int i = 0;i < n-1 ; i++){
        int a,b ; cin >> a >> b;
        a -= offset, b -= offset;
        T c; cin >> c;
        res[a].emplace_back(b,c);
        res[b].emplace_back(a,c);
    }
    return res;
}

signed main(){
    // ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);cout<<fixed<<setprecision(15);
    INT(n);
    tree g = make(n);
    vector<int> sub(n);
    int centroid;
    vector<int> centroids;
    {
        auto dfs = [&](auto &&f,int x,int p)->int{
            sub[x] = 1;
            for(auto e:g[x]) if(e!=p) sub[x] += f(f,e,x);
            return sub[x];
        };
        dfs(dfs,0,-1);
        auto search = [&](auto &&f,int x,int p)->int{
            for(auto e:g[x]){
                if(e == p) continue;
                if(sub[e] > n/2) return f(f,e,x);
            }
            return x;
        };
        centroid = search(search,0,-1);
        dfs(dfs,centroid,-1);
        rep(i,n) if(~n&1 and sub[i] == n/2) centroids.eb(i);
        centroids.eb(centroid);
    }
    vector<int> top(n),tail(n);
    vector<tuple<int,int,int>> ans;
    auto dfs = [&](auto &&f,int x,int p,int c,int cc)->void{
        if(p!=c and p!= cc){
            ans.eb(c,cc,x);
            ans.eb(x,p,cc);
            ans.eb(c,x,cc);
        }
        for(auto e:g[x]) if(e != p) f(f,e,x,c,cc);
        return ;
    };
    vector<bool> ng(n);
    for(auto c:centroids) ng[c] = true;
    for(auto c:centroids){
        for(auto cc:g[c]){
            if(!ng[cc])
            dfs(dfs,cc,c,c,cc);
        }
    }
    vector<tuple<int,int,int>> ANS;
    using T = tuple<int,int,int>;
    auto same = [](T x,T y){
        return get<0>(x) == get<0>(y) and get<2>(x) == get<1>(y);
    };
    rep(i,ans.size()){
        if(i < ans.size()-1 and same(ans[i],ans[i+1])){
            i++;continue;
        }
        ANS.eb(ans[i]);
    }
    cout << ANS.size() << endl;
    for(auto [a,b,c] :ANS){
        cout << ++ a << " " << ++ b << " " << ++ c << endl;
    }

}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

const int INF = (int) 1e9 + 123;
const ll LINF = (ll) 1e18 + 123;
const ld EPS = (ld) 1e-12;
const ll MOD = (ll) 1e9 + 7;

#define sz(x) (int) (x).size()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define lb(s, t, x) (int) (lower_bound(s, t, x) - s)
#define ub(s, t, x) (int) (upper_bound(s, t, x) - s)
#define rep(i, f, t) for (auto i = f; i < t; i++)
#define per(i, f, t) for (auto i = f; i >= t; i--)

ll power(ll x, ll y, ll mod = MOD) {
    if (y == 0) {
        return 1;
    }
    if (y & 1) {
        return power(x, y - 1, mod) * x % mod;
    } else {
        ll tmp = power(x, y / 2, mod);
        return tmp * tmp % mod;
    }
}

inline void add(ll &x, ll y, ll mod = MOD) {
    x += y;
    if (x >= mod) x -= mod;
    if (x < 0) x += mod;
}

inline ll sum(ll x, ll y, ll mod = MOD) {
    add(x, y, mod);
    return x;
}

inline ll mult(ll x, ll y, ll mod = MOD) {
    return (x * y) % mod;
}

inline ll div(ll x, ll y, ll mod) {
    return x * power(y, mod - 2, mod);
}

template<typename A, typename B> inline bool mini(A &x, const B &y) {
    if (y < x) {
        x = y;
        return true;
    }
    return false;
}

template<typename A, typename B> inline bool maxi(A &x, const B &y) {
    if (y > x) {
        x = y;
        return true;
    }
    return false;
}

template<typename T> inline void read(T first, T last) {
    while (first != last) {
        cin >> *(first++);
    }
}

template<typename T> inline void print(T first, T last) {
    while (first != last) {
        cout << *(first++) << " ";
    }
    cout << "\n";
}

void run();

#define TASK ""

int main() {
#ifdef LOCAL
    if (strlen(TASK) > 0) {
        cerr << "Reminder: you are using file i/o, filename: " TASK "!" << endl << endl;
    }
#endif
#ifndef LOCAL
    if (strlen(TASK)) {
        freopen(TASK ".in", "r", stdin);
        freopen(TASK ".out", "w", stdout);
    }
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif
    cout << fixed << setprecision(12);
    run();
    return 0;
}

// == SOLUTION == //

const int N = (int) 2e5 + 123;

struct Q {
    int x, y1, y2;
};

int n;
vector<pair<int, int>> g[N];
vector<Q> res;
bool vis[N], used[N];
int cnt[N];

void calc_cnt(int v, int p = -1) {
    cnt[v] = 1;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || u == p || used[e.second]) continue;
        calc_cnt(u, v);
        cnt[v] += cnt[u];
    }
}

int dfs(int v);

pair<bool, int> centroid_edge(int v, int all, int p = -1) {
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || u == p || used[e.second]) continue;
        auto tmp = centroid_edge(u, all, v);
        if (tmp.first) return tmp;
        if (2 * cnt[u] == all) {
            used[e.second] = 1;
            dfs(v);
            dfs(u);
            return {1, u};
        }
    }
    return {0, -1};
}

void find_centroid(int v, int all, int &x, int p = -1) {
    bool ok = 1;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || used[e.second]) continue;
        ok &= 2 * (u != p ? cnt[u] : all - cnt[v]) < all;
        if (u == p) continue;
        find_centroid(u, all, x, v);
    }
    if (ok) {
        assert(x == -1);
        x = v;
    }
}

int dfs(int v) {
    calc_cnt(v);
    auto tmp = centroid_edge(v, cnt[v]);
    if (tmp.first) {
        return tmp.second;
    }

    int centroid = -1;
    find_centroid(v, cnt[v], centroid);
    assert(centroid != -1);
    v = centroid;
    vis[v] = 1;
    vector<Q> cur;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || used[e.second]) continue;
        int t = dfs(u);
        if (1) cur.push_back({v, u, t});
    }
    for (Q &q : cur) {
        res.pb(q);
    }
    return v;
}

void massert(bool x) {
    if (!x) {
        cerr << "bad" << endl;
    }
    #ifndef LOCAL
    assert(x);
    #endif
}

void run() {
    cin >> n;
    rep(i, 0, n - 1) {
        int u, v;
        cin >> u >> v;
        g[u].pb({v, i});
        g[v].pb({u, i});
    }

    dfs(1);

    cout << sz(res) << "\n";
    memset(vis, 0, sizeof vis);
    calc_cnt(1);
    reverse(all(res));
    for (Q &q : res) {
        if (cnt[q.x] < cnt[q.y1]) {
            //massert(cnt[q.x] > n - cnt[q.x]);
        } else {
            //massert(n - cnt[q.y1] > cnt[q.y1]);
        }
        cout << q.x << " " << q.y1 << " " << q.y2 << "\n";
    }
}

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

struct Transformation {
	const int x, y, yp;
};

const int MAX_N = 2e5;

int n, sizeOfSubtree[MAX_N + 1], centroid, leaf[MAX_N + 1];
pair<int, int> centroids;
bool singleCentroid;
unordered_set<int> adjacencyList[MAX_N + 1];
vector<Transformation> transformations;

template<typename valueType, template<typename = valueType, typename... arguments> class containerType>
vector<valueType> copy(const containerType<valueType>& container) {
	vector<valueType> result;
	result.reserve(container.size());
	for (const valueType element : container)
		result.push_back(element);
	return result;
}

void removeEdge(const int vertex, const int adjacent) {
	// cout << "removing edge between " << vertex << " and " << adjacent << endl;
	/*
	cout << "vertex adjacents (before): " << endl;
	for (int a : adjacencyList[vertex])
		cout << a << endl;
	cout << "adjacent adjacents (before): " << endl;
	for (int a : adjacencyList[adjacent])
		cout << a << endl;
	*/
	adjacencyList[vertex].erase(adjacent);
	adjacencyList[adjacent].erase(vertex);
	// cout << "edge removed" << endl;
	return;
}

void addEdge(const int vertex, const int adjacent) {
	// cout << "adding edge between " << vertex << " and " << adjacent << endl;
	/*
	cout << "vertex adjacents (before): " << endl;
	for (int a : adjacencyList[vertex])
		cout << a << endl;
	cout << "adjacent adjacents (before): " << endl;
	for (int a : adjacencyList[adjacent])
		cout << a << endl;
	*/
	adjacencyList[vertex].insert(adjacent);
	adjacencyList[adjacent].insert(vertex);
	// cout << "edge added" << endl;
	return;
}

void transform(const int x, const int y, const int yp) {
	// cout << "trasnforming on " << x << ' ' << y << ' ' << yp << endl;
	removeEdge(x, y);
	addEdge(x, yp);
	transformations.push_back({x, y, yp});
	// cout << "done transforming on " << x << ' ' << y << ' ' << yp << endl;
	return;
}

void calculateSizeOfSubtrees(const int root, const int parent) {
	/*
	cout << "in calculate size of subtree" << endl;
	cout << "root: " << root << endl;
	cout << "parent: " << parent << endl;
	*/
	sizeOfSubtree[root] = 1;
	for (const int adjacent : copy(adjacencyList[root])) {
		if (adjacent != parent) {
			calculateSizeOfSubtrees(adjacent, root);
			sizeOfSubtree[root] += sizeOfSubtree[adjacent];
		}
	}
	/*
	cout << "size of subtree: " << sizeOfSubtree[root] << endl;
	cout << "root: " << root << endl;
	cout << "parent: " << parent << endl;
	*/
	return;
}

void calculateCentroid() {
	// cout << "in calculate centroid" << endl;
	int root = 1;
	bool foundCentroid = false;
	calculateSizeOfSubtrees(root, -1);
	while (not foundCentroid) {
		// cout << "root: " << root << endl;
		foundCentroid = true;
		for (const int adjacent : copy(adjacencyList[root])) {
			if (sizeOfSubtree[adjacent] * 2 > n) {
				// cout << "root cannot be centroid because of an adjacent" << endl;
				// cout << "root: " << root << endl;
				// cout << "adjacent: " << adjacent << endl;
				foundCentroid = false;
				sizeOfSubtree[root] = n - sizeOfSubtree[adjacent];
				sizeOfSubtree[adjacent] = n;
				root = adjacent;
				// cout << "updated sizes: " << endl;
				/*for (int v = 1; v <= n; ++v)
					cout << sizeOfSubtree[v] << ' ';
				cout << endl;*/
				break;
			} else if (sizeOfSubtree[adjacent] * 2 == n) {
				// cout << "root and its adjacent are centroids together" << endl;
				// cout << "root: " << root << endl;
				// cout << "adjacent: " << adjacent << endl;
				singleCentroid = false;
				centroids = {root, adjacent};
				return;
			}
		}
	}
	//cout << "finally, our signle centroid is: " << root << endl;
	singleCentroid = true;
	centroid = root;
	return;
}

void makeAdjacentBamboo(const int vertex, const int adjacent) {
	// cout << "in make adjacent bamboo" << endl;
	// cout << "vertex: " << vertex << endl;
	// cout << "adjacent: " << adjacent << endl;
	if (adjacencyList[adjacent].size() == 1) {
		// cout << "adjacent is leaf" << endl;
		// cout << "vertex: " << vertex << endl;
		// cout << "adjacent: " << adjacent << endl;
		leaf[adjacent] = adjacent;
		if (adjacencyList[vertex].size() <= 2) {
			// cout << "vertex is leaf/pre-root" << endl;
			leaf[vertex] = adjacent;
		}
	} else {
		// cout << "adjacnet is not a leaf" << endl;
		// cout << "vertex: " << vertex << endl;
		// cout << "adjacent: " << adjacent << endl;
		for (const int adjacentOfAdjacent : copy(adjacencyList[adjacent])) {
			// cout << "in the loop" << endl;
			// cout << "vertex: " << vertex << endl;
			//cout << "adjacent: " << adjacent << endl;
			//cout << "adjacent of adjacent: " << adjacentOfAdjacent << endl;
			if (adjacentOfAdjacent != vertex) {
				//cout << "calling make adjacent bamboo" << endl;
				makeAdjacentBamboo(adjacent, adjacentOfAdjacent);
			}
		}
		//cout << "after loop" << endl;
		//cout << "vertex: " << vertex << endl;
		//cout << "adjacnet: " << adjacent << endl;
		if (adjacencyList[adjacent].size() <= 2) {
			//cout << "adjacent is bamboo" << endl;
			if (adjacencyList[vertex].size() <= 2) {
				//cout << "vertex is leaf/pre-root" << endl;
				leaf[vertex] = leaf[adjacent];
			}
		} else {
			//cout << "adjacent is not bamboo" << endl;
			int adjacentOfAdjacent = *adjacencyList[adjacent].begin();
			if (adjacentOfAdjacent == vertex)
				adjacentOfAdjacent = *(++adjacencyList[adjacent].begin());
			//cout << "adjacent of adjacent: " << adjacentOfAdjacent << endl;
			transform(vertex, adjacent, leaf[adjacentOfAdjacent]);
			//cout << "calling make adjacent bamboo" << endl;
			makeAdjacentBamboo(adjacentOfAdjacent, adjacent);
			if (adjacencyList[vertex].size() <= 2) {
				//cout << "vertex is leaf/pre-root" << endl;
				//cout << "vertex: " << vertex << endl;
				//cout << "adjacnet: " << adjacent << endl;
				leaf[vertex] = leaf[adjacentOfAdjacent];
			}
		}
	}
	//cout << "done making adjacent bamboo" << endl;
	//cout << "vertex: " << vertex << endl;
	//cout << "adjacent: " << adjacent << endl;
	return;
}

void makeAdjacentHedgehog(const int vertex, const int adjacent) {
	//cout << "in make adjacent hedgehog" << endl;
	//cout << "vertex: " << vertex << endl;
	//cout << "adjacent: " << adjacent << endl;
	if (adjacencyList[adjacent].size() == 1) {
		//cout << "p2 does not need any operation" << endl;
		//cout << "done making hedgehog" << endl;
		return;
	}
	makeAdjacentBamboo(vertex, adjacent);
	const int hedgehogCenter = *adjacencyList[leaf[adjacent]].begin();
	//cout << "hedgehog's center: " << hedgehogCenter << endl;
	int lastSpine = *adjacencyList[hedgehogCenter].begin();
	if (lastSpine == leaf[adjacent])
		lastSpine = *(++adjacencyList[hedgehogCenter].begin());
	while (lastSpine != vertex) {
		//cout << "last spine: " << lastSpine << endl;
		int adjacentOfLastSpine = *adjacencyList[lastSpine].begin();
		if (adjacentOfLastSpine == hedgehogCenter)
			adjacentOfLastSpine = *(++adjacencyList[lastSpine].begin());
		//cout << "adjacent of last spine: " << adjacentOfLastSpine << endl;
		transform(adjacentOfLastSpine, lastSpine, hedgehogCenter);
		lastSpine = adjacentOfLastSpine;
	}
	//cout << "done making hedgehog" << endl;
	//cout << "vertex: " << vertex << endl;
	//cout << "adjacent: " << adjacent << endl;
	return;
}

void optimizeIO() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
}

int main() {
	optimizeIO();
	//cout << "in main" << endl;
	cin >> n;
	for (int i = 1, a, b; i <= n - 1; ++i) {
		cin >> a >> b;
		addEdge(a, b);
	}
	//cout << "read inputs" << endl;
	calculateCentroid();
	//cout << "calculated centroids" << endl;
	//cout << boolalpha << "single centroid: " << singleCentroid << endl;
	if (singleCentroid)
		for (const int adjacent : copy(adjacencyList[centroid]))
			makeAdjacentHedgehog(centroid, adjacent);
	else {
		for (const int adjacent : copy(adjacencyList[centroids.first]))
			if (adjacent != centroids.second)
				makeAdjacentHedgehog(centroids.first, adjacent);
		for (const int adjacent : copy(adjacencyList[centroids.second]))
			if (adjacent != centroids.first)
				makeAdjacentHedgehog(centroids.second, adjacent);
	}
	//cout << "printing output" << endl;
	if (singleCentroid) {
		for (const int centroidAdjacent : adjacencyList[centroid])
			for (const int adjacentToCentroidAdjacent : adjacencyList[centroidAdjacent])
				if (adjacentToCentroidAdjacent != centroid and adjacencyList[adjacentToCentroidAdjacent].size() != 1) {
					for (int vertex = 1; vertex <= n; ++vertex)
						cout << adjacencyList[vertex].size() << ' ';
					cout << endl;
					return 0;
				}
	} else {
		for (const int centroidAdjacent : adjacencyList[centroids.first])
			if (centroidAdjacent != centroids.second)
				for (const int adjacentToCentroidAdjacent : adjacencyList[centroidAdjacent])
					if (adjacentToCentroidAdjacent != centroids.first and adjacencyList[adjacentToCentroidAdjacent].size() != 1) {
						cout << ":|" << endl;
						return 0;
					}
		for (const int centroidAdjacent : adjacencyList[centroids.second])
			if (centroidAdjacent != centroids.first)
				for (const int adjacentToCentroidAdjacent : adjacencyList[centroidAdjacent])
					if (adjacentToCentroidAdjacent != centroids.second and adjacencyList[adjacentToCentroidAdjacent].size() != 1) {
						cout << ":|" << endl;
						return 0;
					}
	}
	cout << transformations.size() << '\n';
	for (Transformation& transformation : transformations)
		cout << transformation.x << ' ' << transformation.y << ' ' << transformation.yp << '\n';
	return 0;
}

#include <bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define pii pair<int,int>
#define pll pair<ll,ll>
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define pb push_back
#define PI 3.14159265
#define nmax 100100
const ll inf = std::numeric_limits<ll>::max();
const ll mod = 1e9+7;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

int n,endd[nmax];
set<int> g[nmax];
set<int> s;
vector<int> ans[3];

int cen(int i,int p){
    int mx,ted;
    mx = ted = 0;
    ted++;
    for(auto j : g[i]){
        if(j==p) continue;
        int c = cen(j,i);
        ted+=c;
        mx = max(mx,c);
    }
    mx = max(mx,n-ted);
    if(mx <= n/2){
        s.insert(i);
    }
    return ted;
}

void make1(int i,int p){
    set<int> u = g[i];
    for(auto j : u){
        if(j==p) continue;
        make1(j,i);
    }
    if(s.find(i) != s.end() || g[i].size() == 1) return;
    g[p].erase(i);
    g[i].erase(p);
    vector<int> vnow;
    for(auto j : g[i]) if(j!=p) vnow.pb(j);
    endd[endd[vnow[0]]] = i;
    g[p].insert(endd[vnow[0]]);
    g[endd[vnow[0]]].insert(p);
    ans[0].pb(p),ans[1].pb(i),ans[2].pb(endd[vnow[0]]);
    fo(j,0,vnow.size()-1){
        ans[0].pb(vnow[j]),ans[1].pb(i),ans[2].pb(endd[vnow[j+1]]);
        g[i].erase(vnow[j]);
        g[vnow[j]].erase(i);
        g[endd[vnow[j+1]]].insert(vnow[j]);
        g[vnow[j]].insert(endd[vnow[j+1]]);
    }
}

void make2(int i,int p){
    for(auto j : g[i]){
        if(j==p) continue;
        vector<int> vnow;
        int c = j;
        int pp = p;
        vnow.pb(j);
        while(g[c].size()!=1){
            int csave = c;
            for(auto kk : g[c]){
                if(kk != pp) c = kk;
            }
            pp = csave;
            vnow.pb(c);
        }
        reverse(vnow.begin(),vnow.end());
        fo(k,3,vnow.size()){
            ans[0].pb(vnow[k]),ans[1].pb(vnow[k-1]),ans[2].pb(vnow[1]);
        }
        if(vnow.size() >= 3) ans[0].pb(i),ans[1].pb(j),ans[2].pb(vnow[1]);
    }
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin >> n;
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--;y--;
        g[x].insert(y);
        g[y].insert(x);
    }
    fo(i,0,n) endd[i] = i;
    cen(0,-1);
    if(s.size() == 2){
        make1(*s.begin(),*s.rbegin());
        make1(*s.rbegin(),*s.begin());
        make2(*s.begin(),*s.rbegin());
        make2(*s.rbegin(),*s.begin());
    }else{
        make1(*s.begin(),-1);
        make2(*s.begin(),-1);
    }
    cout << ans[0].size() << '\n';
    fo(i,0,ans[0].size()){
        cout << ans[0][i]+1 << ' ' << ans[1][i]+1 << ' ' << ans[2][i]+1 << '\n';
    }

    return 0;
}

#define DEB
#include<bits/stdc++.h>
#define REP(i,m) for(int i=0;i<(m);++i)
#define REPN(i,m,in) for(int i=(in);i<(m);++i)
#define ALL(t) (t).begin(),(t).end()
#define CLR(a) memset((a),0,sizeof(a))
#define pb push_back
#define mp make_pair
#define fr first
#define sc second

using namespace std;

#ifdef DEB
#define dump(x)  cerr << #x << " = " << (x) << endl
#define prl cerr<<"called:"<< __LINE__<<endl
#define dumpR(x) cerr<<"\x1b[31m"<<#x<<" = " <<(x)<<"\x1b[39m"<<endl
#define dumpY(x) cerr<<"\x1b[33m"<<#x<<" = " <<(x)<<"\x1b[39m"<<endl
#define dumpG(x) cerr<<"\x1b[32m"<<#x<<" = " <<(x)<<"\x1b[39m"<<endl
template<class T> void debug(T a,T b){ for(;a!=b;++a) cerr<<*a<<' ';cerr<<endl;}
#else
#define dump(x) ;
#define dumpR(x) ;
#define dumpY(x) ;
#define dumpG(x) ;
#define prl ;
template<class T> void debug(T a,T b){ ;}
#endif

template<class T> void chmin(T& a,const T& b) { if(a>b) a=b; }
template<class T> void chmax(T& a,const T& b) { if(a<b) a=b; }

typedef long long int lint;
typedef pair<int,int> pi;

namespace std{
  template<class S,class T>
  ostream &operator <<(ostream& out,const pair<S,T>& a){
    out<<'('<<a.fr<<','<<a.sc<<')';
    return out;
  }
}

const int INF=5e8;
int n;
vector<int> g[200005];

vector<pair<int,pi> >ans;
static const int MAX_N=200005;
int cut[MAX_N],size[MAX_N],whole;
int root,rcost;
int getsize(int v,int p){
  size[v]=1;
  REP(i,g[v].size()){
    int to=g[v][i];
    if(to!=p && cut[to]==0) size[v]+=getsize(to,v);
  }
  return size[v];
}
void getbestroot(int v,int p){
  int maxi=0;
  REP(i,g[v].size()){
    int to=g[v][i];
    if(to!=p && cut[to]==0){
      getbestroot(to,v);
      maxi=max(maxi,size[to]);
    }
  }
  int rest=whole-size[v];
  maxi=max(maxi,rest);
  if(maxi<rcost){
    rcost=maxi;
    root=v;
  }
}

int dfs(int v){
  getsize(v,-1);
  if(size[v]==1) return v;
  whole=size[v];
  rcost=INF;
  getbestroot(v,-1);
  v=root;

  cut[v]=1;

  REP(i,g[v].size()){
    int to=g[v][i];
    if(cut[to]==0){
      int v2=dfs(to);
      if(to!=v2) ans.pb({v,{to,v2}});
    }
  }
  cut[v]=0;
  return v;
}

int main(){
#ifdef LOCAL_REDIR
  freopen("/home/hog/Dropbox/pg/working/in.txt","r",stdin);
#endif
  cin>>n;
  REP(i,n-1){
    int a,b;scanf("%d%d",&a,&b);--a;--b;
    g[a].pb(b);
    g[b].pb(a);
  }

  dfs(0);

  reverse(ALL(ans));
  cout<<ans.size()<<endl;
  for(auto e:ans){
    printf("%d %d %d\n",e.fr+1,e.sc.fr+1,e.sc.sc+1);
  }
  return 0;
}

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define N 200010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,p[N],size[N],stkx[N],stky[N],stkz[N],top,t;
vector<int> son[N],son2[N];
bool flag[N];
struct data{int to,nxt;
}edge[N<<1];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void make(int k,int from)
{
    size[k]=1;
    for (int i=p[k];i;i=edge[i].nxt)
    if (edge[i].to!=from&&!flag[edge[i].to])
    {
        make(edge[i].to,k);
        size[k]+=size[edge[i].to];
    }
}
int findroot(int k,int s,int from)
{
    int mx=0;
    for (int i=p[k];i;i=edge[i].nxt)
    if (edge[i].to!=from&&!flag[edge[i].to]&&size[edge[i].to]>size[mx]) mx=edge[i].to;
    if ((size[mx]<<1)>s) return findroot(mx,s,k);
    else return k;
}
int solve(int k)
{
	make(k,k);
	k=findroot(k,size[k],k);flag[k]=1;
	if (size[k]==n&&n%2==0)
	{
		int x=0;
		for (int i=1;i<=n;i++)
		if (size[i]==n/2) {x=i;break;}
		if (x)
		{
			flag[x]=1;
			for (int i=p[k];i;i=edge[i].nxt)
			if (!flag[edge[i].to]) son[k].push_back(solve(edge[i].to)),son2[k].push_back(edge[i].to);
			for (int i=p[x];i;i=edge[i].nxt)
			if (!flag[edge[i].to]) son[x].push_back(solve(edge[i].to)),son2[x].push_back(edge[i].to);
			for (int i=0;i<son[k].size();i++)
			{
				top++;
				stkx[top]=k;
				stky[top]=son2[k][i];
				stkz[top]=son[k][i];
			}
			for (int i=0;i<son[x].size();i++)
			{
				top++;
				stkx[top]=x;
				stky[top]=son2[x][i];
				stkz[top]=son[x][i];
			}
		}
	}
	for (int i=p[k];i;i=edge[i].nxt)
	if (!flag[edge[i].to]) son[k].push_back(solve(edge[i].to)),son2[k].push_back(edge[i].to);
	for (int i=0;i<son[k].size();i++)
	{
		top++;
		stkx[top]=k;
		stky[top]=son2[k][i];
		stkz[top]=son[k][i];
	}
	return k;
}
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	n=read();
	for (int i=1;i<n;i++)
	{
		int x=read(),y=read();
		addedge(x,y),addedge(y,x);
	}
	solve(1);
	cout<<top<<endl;
	for (int i=top;i>=1;i--) printf("%d %d %d\n",stkx[i],stky[i],stkz[i]);
	return 0;
	//NOTICE LONG LONG!!!!!
}

// In the name of Allah.
// We're nothing and you're everything.
// Ya Ali!

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 14;
int n;
struct Trans{
	int x, y, yp;
};
vector<Trans> ans;
vector<int> g[maxn];
bool mark[maxn];
pair<int, int> far(int v, int p = -1){
	pair ans(0, v);
	for(auto u : g[v])
		if(!mark[u] && u != p)
			ans = max(ans, far(u, v));
	ans.first++;
	return ans;
}
bool pat(int v, int p, int dest, vector<int> &path){
	path.push_back(v);
	if(v == dest)
		return 1;
	for(auto u : g[v])
		if(!mark[u] && u != p && pat(u, v, dest, path))
			return 1;
	path.pop_back();
	return 0;
}
vector<int> cen(int v){
	int fs = far(v).second;
	int ss = far(fs).second;
	std::vector<int> vec;
	pat(fs, -1, ss, vec);
	if(vec.size() % 2)
		return {vec[vec.size() / 2]};
	else
		return {vec[vec.size() / 2 - 1], vec[vec.size() / 2]};
}
void pull(int v){
	mark[v] = 1;
	for(auto u : g[v])
		if(!mark[u]){
			int c = cen(u)[0];
			if(c != u)
				ans.push_back({v, u, c});
			pull(c);
		}
}
int main(){
	ios::sync_with_stdio(0), cin.tie(0);
	cin >> n;
	for(int i = 1; i < n; i++){
		int v, u;
		cin >> v >> u;
		v--, u--;
		g[v].push_back(u);
		g[u].push_back(v);
	}
	auto cs = cen(0);
	for(auto v : cs)
		mark[v] = 1;
	for(auto v : cs)
		pull(v);
	cout << ans.size() << '\n';
	for(auto [x, y, yp] : ans)
		cout << x + 1 << ' ' << y + 1 << ' ' << yp + 1 << '\n';
}

#include <bits/stdc++.h>

using namespace std;
#define ll long long
#define ld long double
#define mk make_pair
#define pb push_back
#define sz(a) (int)(a).size()
#define rep(i, a, b) for (int i = (a), _b = (b); i < _b; ++i)

typedef complex<ld> cplex;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef pair<ii, int> iii;
typedef vector<ii> vii;
typedef vector<iii> viii;

const int inf = 1000000007;
const int N = 200000 + 7;
const int M = 10;
const int multipleTest = 0;

vi adj[N];
int n;

iii res[2 * N];
int top = 0;
int f[N];

set<int> rev[N];
bool check[N];

void dfs(int u, int r) {
    f[u] = 1;
    for (int v : adj[u]) {
        if (v != r) {
            dfs(v, u);
            f[u] += f[v];
        }
    }
}

void swapEdge(int x, int u, int v) {
    if (u == v) return;
    res[top++] = (mk(mk(x, u), v));

    rev[x].erase(u);
    rev[u].erase(x);

    rev[x].insert(v);
    rev[v].insert(x);
}

ii go(int u, int r) {
    vii ls; ls.clear();
    for (int v : adj[u]) if (v != r) {
        ii x = go(v, u);
        ls.push_back(x);
    }
    if (ls.empty()) return mk(u, u);
    if (ls.size() == 1) {
        return mk(ls[0].first, u);
    } else {

        for (int j = ls.size() - 1; j > 0; --j) {
            swapEdge(ls[j - 1].second, u, ls[j].first);
        }

        return mk(ls[0].first, u);
    }
}

void buildTree(int u, int r) {
    int len = top;
    int x = go(u, r).first;
    swapEdge(r, u, x);
    reverse(res + len, res + top);
    vi cur;
    cur.push_back(r);
    check[r] = 1;
    cur.push_back(x);
    check[x] = 1;
    while (true) {
        bool found = false;
        assert(rev[cur.back()].size() <= 2);
        for (int v : rev[cur.back()]) {
            if (!check[v]) {
                cur.push_back(v);
                check[v] = 1;
                found = true;
                rev[cur.back()].erase(v);
                break;
            }
        }
        if (!found) break;
    }

//    for (int x : cur) cout << x << ' ';
//    puts("");

    for (int j = (int)cur.size() - 4; j >= 0; --j) {
        swapEdge(cur[j], cur[j + 1], cur[cur.size() - 2]);
    }
}

void findCentroid() {
    dfs(1, -1);
    int u = 1;
    int r = -1;
    for (bool found = true; found; ) {
        found = false;
        for (int v : adj[u]) {
            if (v != r && f[v] > n / 2) {
                found = true;
                r = u;
                u = v;
                break;
            }
        }
        if (n == 200000) cout << u << '\n';
    }
    int u1 = -1;
    for (int v : adj[u]) if (v != r && f[v] == n - f[v]) {
        u1 = v;
    }
    if (n == 200000) return;
    if (u1 == -1) {
        for (int v : adj[u]) buildTree(v, u);
    } else {
        check[u] = check[u1] = 1;
        for (int v : adj[u]) if (v != u1) buildTree(v, u);
        for (int v : adj[u1]) if (v != u) buildTree(v, u1);
    }
}

void solve() {
    cin >> n;
    rep(i, 1, n) {
        int u, v;
        scanf("%d%d", &u, &v);
        adj[u].push_back(v);
        adj[v].push_back(u);
        rev[u].insert(v);
        rev[v].insert(u);
    }

    findCentroid();

    cout << top << '\n';
    for (iii& x : res) {

        if (!top) break;
        top--;
        printf("%d %d %d\n", x.first.first, x.first.second, x.second);
    }

}

int main() {
#ifdef _LOCAL_
    freopen("in.txt", "r", stdin);
    //    freopen("out.txt", "w", stdout);
#endif
    int Test = 1;
    if (multipleTest) {
        cin >> Test;
    }
    for(int i = 0; i < Test; ++i) {
        solve();
    }
#ifdef _LOCAL_
    cout<<"\n" << 1.0 * clock() / CLOCKS_PER_SEC <<endl;
#endif
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define pb push_back
#define mp make_pair

int n;
set<int> g[200010];
queue<pii> q[200010];
char c[200010];
set<int> centers;
struct tup{
    int x, y, yy, p;
    tup(int x, int y, int yy): x(x), y(y), yy(yy) {}
};
vector<tup> ans;
queue<tup> tmp;
vector<int> cur;
int d[200010];

void dfs1(int v, int p){
    for(auto to: g[v]){
        if(to != p){
            dfs1(to, v);
            d[v] += d[to];
        }
    }
    d[v]++;
}

void find_centers(){
    dfs1(0, 0);
    for(int i = 0; i < n; i++){
        bool canCenter = true;
        for(auto to: g[i]){
            int cursz;
            if(d[to] < d[i]) cursz = d[to];
            else cursz = n - d[i];
            if(cursz > n / 2) canCenter = false;
        }
        if(canCenter){
            c[i] = true;
            centers.insert(i);
        }
    }
}

void freeQ(){
    while(!tmp.empty()){
        tup u = tmp.front();
        tmp.pop();
        g[u.x].erase(u.y);
        g[u.y].erase(u.x);
        g[u.x].insert(u.yy);
        g[u.yy].insert(u.x);
        //cout << "HERE " << u.x + 1 << ' ' << u.y + 1 << ' ' << u.yy + 1 << endl;
    }
}

int go(int v, int p){
    for(auto to: g[v]){
        if(to != p) return go(to, v);
    }
    return v;
}

void solve(int v, int p){
    //cout << v + 1 << ' ' << p + 1 << endl;
    if(v >= 21) return;
    vector<int> t;
    for(auto to: g[v]) if(to != p) t.pb(to);
    for(auto to: t){
        solve(to, v);
    }
    for(auto to: g[v]){
        if(to != p){
            q[v].push(mp(go(to, v), to));
        }
    }
    while(q[v].size() > 1){
        ans.pb(tup(p, v, q[v].front().first));
        tmp.push(tup(p, v, q[v].front().first));
        p = q[v].front().second;
        q[v].pop();
    }
    freeQ();
}

void solve2(int v, int p){
    cur.pb(v);
    for(auto to: g[v]){
        if(to != p) solve2(to, v);
    }
}

void gen_graph(){
    char used[1234] = {};
    mt19937 mt(123);
    used[0] = true;
    for(int i = 0; i < n - 1; i++){
        int from, to;
        while(true){
            from = mt() % n;
            to = mt() % n;
            if(from != to && (!used[from] && used[to] || used[from] && !used[to])) break;
        }
        used[from] = true;
        used[to] = true;
        g[from].insert(to);
        g[to].insert(from);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n;
    for(int i = 0; i < n - 1; i++){
        int from, to;
        cin >> from >> to;
        g[from - 1].insert(to - 1);
        g[to - 1].insert(from - 1);
    }
    //gen_graph();
    /*for(int i = 0; i < n; i++){
        for(auto to: g[i]){
                if(i < to) cout << i + 1 << ' ' << to + 1 << endl;
        }
    }
    cout << endl;*/
    find_centers();
    for(auto u: centers){
        //cout << u + 1 << endl;
        vector<int> t;
        for(auto v: g[u]) if(!c[v]) t.pb(v);
        for(auto v: t){
            solve(v, u);
            //cout << endl;
        }
    }
    freeQ();
    /*cout << endl;
    for(int i = 0; i < n; i++){
        for(auto to: g[i]){
                if(i < to) cout << i + 1 << ' ' << to + 1 << endl;
        }
    }
    cout << endl;*/
    for(auto u: centers){
        for(auto to: g[u]){
            if(c[to]) continue;
            cur.clear();
            cur.pb(u);
            solve2(to, u);
            cur.pop_back();
            int last = cur.back();
            cur.pop_back();
            for(int i = (int)cur.size() - 1; i >= 1; i--){
                ans.pb(tup(cur[i - 1], cur[i], last));
            }
        }
    }
    cout << ans.size() << endl;
    for(auto u: ans){
        cout << u.x + 1 << ' ' << u.y + 1 << ' ' << u.yy + 1 << endl;
    }
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
int sub[200000];

void dfs(int i,int p,vector<vector<int> > &e)
{
  sub[i]=1;
  for(int x=0;x<e[i].size();x++){
    int j=e[i][x];
    if(j==p){
      continue;
    }
    dfs(j,i,e);
    sub[i]+=sub[j];
  }
}

pair<int,int> cent(vector<vector<int> > &e)
{
  dfs(0,-1,e);
  int a=0,b,p=-1,n=sub[0];
  while(1){
    int S=0,q=-1;
    for(int x=0;x<e[a].size();x++){
      int j=e[a][x];
      if(j==p){
	continue;
      }
      if(S<sub[j]){
	S=sub[j];
	q=j;
      }
    }
    if(S<=n/2){
      if(2*S==n){
	b=q;
      }
      else{
	b=-1;
      }
      break;
    }
    p=a;
    a=q;
  }
  return make_pair(a,b);
}

vector<int> ans1,ans2,ans3;

void dfs2(int i,int p,int c,vector<vector<int> > &e,vector<int> &v)
{
  int q=c;
  for(int x=0;x<e[i].size();x++){
    int j=e[i][x];
    if(j==p)continue;
    ans1.push_back(q),ans2.push_back(i),ans3.push_back(j);
    q=j;
    dfs2(j,i,c,e,v);
  }
  v.push_back(i);
}

void sol(int s,int c,vector<vector<int> > &e)
{
  vector<int> v;
  v.push_back(c);
  dfs2(s,c,c,e,v);
  int k=v.size();
  for(int t=k-4;t>=0;t--){
    ans1.push_back(v[t]),ans2.push_back(v[t+1]),ans3.push_back(v[k-2]);
  }
}

int main()
{
  int n;
  scanf("%d",&n);
  vector<vector<int> > e(n);
  for(int t=0;t<n-1;t++){
    int a,b;
    scanf("%d%d",&a,&b);
    a--,b--;
    e[a].push_back(b);
    e[b].push_back(a);
  }
  pair<int,int> ct=cent(e);
  int c1=ct.first,c2=ct.second;
  for(int x=0;x<e[c1].size();x++){
    int i=e[c1][x];
    if(i==c2)continue;
    sol(i,c1,e);
  }
  if(c2!=-1){
    for(int x=0;x<e[c2].size();x++){
      int i=e[c2][x];
      if(i==c1)continue;
      sol(i,c2,e);
    }
  }
  int K=ans1.size();
  printf("%d\n",K);
  for(int i=0;i<K;i++){
    printf("%d %d %d\n",ans1[i]+1,ans2[i]+1,ans3[i]+1);
  }
  return 0;
}

#ifndef __clang__
#pragma GCC optimize "-O3"
#pragma GCC target "tune=native"
#endif
#ifdef ONLINE_JUDGE
#define NDEBUG 1
#endif
#include <stdio.h>
#include <bits/stdc++.h>

#define DESTRUCT2(p, a, b)                      \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);

#define DESTRUCT3(p, a, b, c)                   \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);                           \
  auto c = get<2>(p);

#define DESTRUCT4(p, a, b, c, d)                \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);                           \
  auto c = get<2>(p);                           \
  auto d = get<3>(p);

#define FOR(i, n)     for(lli i = 0; i < (lli)(n); ++i)
#define FORU(i, j, k) for(lli i = (j); i <= (lli)(k); ++i)
#define FORD(i, j, k) for(lli i = (j); i >= (lli)(k); --i)

#define SQ(x) ((x)*(x))

#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define eb emplace_back

using namespace std;

template<typename... As>
struct tpl : public std::tuple<As...> {
  using std::tuple<As...>::tuple;
  tpl(std::tuple<As...> const& b) { std::tuple<As...>::operator=(b); }

  template<typename T = tuple<As...> >
  typename tuple_element<0, T>::type const&
  x() const { return get<0>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<0, T>::type&
  x() { return get<0>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<1, T>::type const&
  y() const { return get<1>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<1, T>::type&
  y() { return get<1>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<2, T>::type const&
  z() const { return get<2>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<2, T>::type&
  z() { return get<2>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<3, T>::type const&
  w() const { return get<3>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<3, T>::type&
  w() { return get<3>(*this); }
};

using lli   = long long int;
using llu   = long long unsigned;

using pii   = tpl<lli, lli>;
using piii  = tpl<lli, lli, lli>;
using piiii = tpl<lli, lli, lli, lli>;
using vi    = vector<lli>;
using vii   = vector<pii>;
using viii  = vector<piii>;
using vvi   = vector<vi>;
using vvii  = vector<vii>;
using vviii = vector<viii>;

template<class T>
using min_queue = priority_queue<T, vector<T>, greater<T> >;
template<class T>
using max_queue = priority_queue<T>;

template<size_t... I>
struct my_index_sequence {
  using type = my_index_sequence;
  static constexpr array<size_t, sizeof...(I)> value = { {I...} };
};

namespace my_index_sequence_detail {
  template<typename I, typename J> struct concat;
  template<size_t... I, size_t... J>
  struct concat<my_index_sequence<I...>, my_index_sequence<J...> > :
    my_index_sequence<I..., (sizeof...(I)+J)...> { };
  template<size_t N> struct make_index_sequence :
    concat<typename make_index_sequence<N/2>::type, typename make_index_sequence<N-N/2>::type>::type { };
  template <> struct make_index_sequence<0> : my_index_sequence<>{};
  template <> struct make_index_sequence<1> : my_index_sequence<0>{};
}

template<class... A>
using my_index_sequence_for = typename my_index_sequence_detail::make_index_sequence<sizeof...(A)>::type;

template<class T, size_t... I>
void print_tuple(ostream& s, T const& a, my_index_sequence<I...>){
  using swallow = int[];
  (void)swallow{0, (void(s << (I == 0? "" : ", ") << get<I>(a)), 0)...};
}

template<class T>
ostream& print_collection(ostream& s, T const& a);
template<class... A>
ostream& operator<<(ostream& s, tpl<A...> const& a);
template<class... A>
ostream& operator<<(ostream& s, tuple<A...> const& a);
template<class A, class B>
ostream& operator<<(ostream& s, pair<A, B> const& a);

template<class T, size_t I>
ostream& operator<<(ostream& s, array<T, I> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, vector<T> const& a) { return print_collection(s, a); }
template<class T, class U>
ostream& operator<<(ostream& s, multimap<T, U> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, multiset<T> const& a) { return print_collection(s, a); }
template<class T, class U>
ostream& operator<<(ostream& s, map<T, U> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, set<T> const& a) { return print_collection(s, a); }

template<class T>
ostream& print_collection(ostream& s, T const& a){
  s << '[';
  for(auto it = begin(a); it != end(a); ++it){
    s << *it;
    if(it != prev(end(a))) s << " ";
  }
  return s << ']';
}

template<class... A>
ostream& operator<<(ostream& s, tpl<A...> const& a){
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}

template<class... A>
ostream& operator<<(ostream& s, tuple<A...> const& a){
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}

template<class A, class B>
ostream& operator<<(ostream& s, pair<A, B> const& a){
  return s << "(" << get<0>(a) << ", " << get<1>(a) << ")";
}

namespace std {
  namespace {
    template <class T>
    inline void hash_combine(size_t& seed, T const& v) {
      seed ^= hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
    }
    template <class Tuple, size_t Index = tuple_size<Tuple>::value - 1>
    struct HashValueImpl {
      static void apply(size_t& seed, Tuple const& tuple) {
        HashValueImpl<Tuple, Index-1>::apply(seed, tuple);
        hash_combine(seed, get<Index>(tuple));
      }
    };
    template <class Tuple>
    struct HashValueImpl<Tuple, 0> {
      static void apply(size_t& seed, Tuple const& tuple) {
        hash_combine(seed, get<0>(tuple));
      }
    };
  }
  template <typename ... TT>
  struct hash<tuple<TT...>> {
    size_t operator()(tuple<TT...> const& tt) const {
      size_t seed = 0;
      HashValueImpl<tuple<TT...> >::apply(seed, tt);
      return seed;
    }
  };
  template <typename ... TT>
  struct hash<tpl<TT...>> {
    size_t operator()(tpl<TT...> const& tt) const {
      size_t seed = 0;
      HashValueImpl<tuple<TT...> >::apply(seed, tt);
      return seed;
    }
  };
}

//------------------------------------------------------------------------------

void test(int n, vii ES, vector<tpl<int,int,int>> ans) {
  vector<set<int>> G(n);
  for(auto const &p :ES) {
    int u,v; tie(u,v) = p;
    G[u].insert(v);
    G[v].insert(u);
  }
  for(auto const& p : ans) {
    int x,y,z; tie(x,y,z) = p;
    assert(G[x].count(y));
    assert(G[y].count(x));
    function<int(int,int)> dfs = [&](int i, int p) {
      int sz=1;
      for(int j : G[i]) if(j!=p) {
          sz+=dfs(j,i);
        }
      return sz;
    };
    int szx = dfs(x,y);
    int szy = dfs(y,x);
    cerr << p << " " << mt(szx,szy) << " " << n << endl;
    assert(szx>szy);
    G[x].erase(y); G[y].erase(x);
    assert(!G[z].count(x));
    assert(!G[x].count(z));
    G[x].insert(z); G[z].insert(x);
  }
}

int main(){
  ios::sync_with_stdio(0); cin.tie(0);
  int n; cin>>n;
  vvi G(n);
  vii ES;
  FOR(i,n-1) {
    int u,v;
    cin>>u>>v;
    --u; --v;
    // u = i+1; v = rand()%(i+1);
    ES.pb(mt(u,v));
    G[u].pb(v);
    G[v].pb(u);
  }

  vi  A(n,0);
  vi  CP(n,-1);
  vi  DP(n,-1);
  int root;
  vi pairWith(n,-1);
  FOR(l,100){
    vi E = A;
    vi P(n);
    vi S(n,1);
    function<void(vi&, int,int)> dfs0 = [&](vi& C, int i,int p){
      E[i]=1; P[i]=p; C.pb(i);
      for(int j : G[i]) if(!A[j] && j!=p) {
          dfs0(C,j,i);
          S[i]+=S[j];
        }
    };
    vi C;
    FOR(i,n) if(!E[i]) {
      C.clear();
      dfs0(C, i, -1);
      auto f = [&](int j){
        int r=0;
        for(auto k : G[j]) if(!A[k] && k!=P[j]) r=max<int>(r,S[k]);
        r=max<int>(r,S[i]-S[j]);
        return r;
      };
      vi centroids; int best=1<<30;
      for(int j : C) {
        int v=f(j);
        if(v<best) { centroids.clear(); best=v; }
        if(v==best) centroids.pb(j);
      }
      for(int j:centroids) A[j]=1;
      if(centroids.size() == 2) {
        pairWith[centroids[0]]=centroids[1];
        pairWith[centroids[1]]=centroids[0];
        CP[centroids[1]]=-1;
      }
      if(CP[centroids[0]]==-1) root=centroids[0];
      function<void(int,int,int,int)> dfs1 = [&](int k, int kk, int i, int p){
        if(i!=k) {CP[i]=k;DP[i]=kk;}
        for(int j : G[i]) if(!A[j] && j!=p) {
            dfs1(k,(kk==-1?j:kk),j,i);
          }
      };
      if(centroids.size() == 1) dfs1(centroids[0],-1,centroids[0],-1);
      else {
        dfs1(centroids[0],-1,centroids[0],centroids[1]);
        dfs1(centroids[1],-1,centroids[1],centroids[0]);
      }
      // // do a dfs on this centroid subtree here :
      // // doDfs(centroid);
      // if(CP[centroid]==-1) root=centroid;
      // for(int j : C) if(j!=centroid) CP[j]=centroid;
    }
    FOR(i,n) if(!A[i]) goto l_beg;
    break;
  l_beg:;
  }

  vvi H(n); FOR(i,n) if(CP[i]!=-1) H[CP[i]].pb(i);

  vi sz(n,0);
  vi sum(n,0);
  function<void(int)> dfs3 = [&](int i0){
    if(pairWith[i0] == -1) {
      sz[i0]=1;
      for(int j : H[i0]) {
        dfs3(j);
        sz[i0] += sz[j];
        sum[i0] += sum[j]+sz[j];
      }
    }else{
      int i1 = pairWith[i0];
      sz[i0]=2;
      for(int j : H[i0]) {
        dfs3(j);
        sz[i0]+=sz[j];
        sum[i0]+=sum[j]+sz[j];
      }
      for(int j : H[i1]) {
        dfs3(j);
        sz[i0]+=sz[j];
        sum[i0]+=sum[j]+sz[j]+sz[j];
      }
    }
  };
  dfs3(root);

  vector<tpl<int,int,int>> ans;

  function<void(int,int)> dfs4 = [&](int i0, int p) {
    if(pairWith[i0] == -1) {
      for(int j : H[i0]) {
        dfs4(j,i0);
      }
      if(DP[i0] != -1 && DP[i0] != i0) ans.pb(mt(p,DP[i0],i0));
    }else{
      int i1 = pairWith[i0];
      int sz0=1,sm0=0,sz1=1,sm1=0;
      for(int j : H[i0]) {
        dfs4(j,i0);
        sz0 += sz[j];
        sm0 += sum[j]+sz[j];
      }
      for(int j : H[i1]) {
        dfs4(j,i1);
        sz1 += sz[j];
        sm1 += sum[j]+sz[j];
      }
      if(DP[i0] != -1) {
        if(2*sm1+sz1<=2*sm0+sz0){
          if(DP[i0]!=i0) ans.pb(mt(p,DP[i0],i0));
        }else{
          if(DP[i0]!=i1) ans.pb(mt(p,DP[i0],i1));
        }
      }
    }
  };
  dfs4(root,-1);

  reverse(all(ans));
  cout << ans.size() << endl;
  for(auto p : ans) {
    int x,y,z; tie(x,y,z) = p;
    cout << x+1 << " " << y+1 << " " << z+1 << '\n';
  }
  cout << flush;

  // cerr << H << " " << sz << endl;
  // cerr << ES << endl;
  // test(n,ES,ans);

  // cerr << pairWith << endl;
  // cerr << H << endl;

  return 0;
}

#include <bits/stdc++.h>
#define fi first
#define se second
#define SZ(x) int((x).size())
#define endl "\n"
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long;
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y, int Mod = mod) { x += y; while (x >= Mod) x -= Mod; while (x < 0) x += Mod; }
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int nextInt() { int x; cin >> x; return x; }
void rd() {}
template <class T, class... Ts> void rd(T& arg, Ts&... args) { cin >> arg; rd(args...); }
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
void err() { cout << "\033[39;0m" << endl; }
template <class T, class... Ts> void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; err(args...); }
void ptt() { cout << endl; }
template <class T, class... Ts> void ptt(const T& arg, const Ts&... args) { cout << ' ' << arg; ptt(args...); }
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg; ptt(args...); }
void pt() {}
template <template<typename...> class T, typename t, typename... A>
void pt(const T <t> &arg, const A&... args) { for (int i = 0, sze = arg.size(); i < sze; ++i) cout << arg[i] << " \n"[i == sze - 1]; pt(args...); }
inline ll qpow(ll base, ll n) { assert(n >= 0); ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
//head
constexpr int N = 2e5 + 10;
int n, sze[N], f[N], fa[N], rt;
vector <int> G[N];

struct E { int x, y, z; };
vector <E> vec;

void dfs(int u) {
	sze[u] = 1;
	for (auto &v : G[u]) {
		if (v == fa[u]) continue;
		fa[v] = u;
		dfs(v);
		sze[u] += sze[v];
		chmax(f[u], sze[v]);
	}
	chmax(f[u], n - sze[u]);
	if (f[u] <= n / 2) rt = u;
}

int dfs2(int u, int rt, int gSon, int top) {
	if (u != rt) {
		vec.push_back({top, gSon, u});
		vec.push_back({u, fa[u], rt});
		gSon = u;
	}
	for (auto &v : G[u]) {
		if (v != fa[u])
			dfs2(v, rt, gSon, top);
	}
	return gSon;
}

void gao(int u, int fa) {
	for (auto &v : G[u]) if (v != fa) {
		int gSon = dfs2(v, v, v, u);
		vec.push_back({u, gSon, v});
	}
}

void run() {
	for (int i = 1, u, v; i < n; ++i) {
		rd(u, v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs(1);
	int x = 0;
	for (int i = 1; i <= n; ++i) {
		if (i != rt && sze[i] * 2 == n) {
			x = i;
		}
	}
	if (!x) {
		dfs(rt);
		gao(rt, 0);
	} else {
		dfs(rt);
		gao(rt, x);
		dfs(x);
		gao(x, rt);
	}
	pt(SZ(vec));
	for (auto &it : vec)
		pt(it.x, it.y, it.z);
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	cout << fixed << setprecision(20);
	while (cin >> n) run();
//    for (int kase = 1; kase <= _T; ++kase) {
//        cout << "Case #" << kase << ":\n";
//        run();
//    }
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define sqr(x) ((x)*(x))
#define par make_pair
#define pb push_back
#define fi first
#define se second
#define endl '\n'
template<class X, class Y> void amax(X& x, const Y& y){if(x < y) x = y;}
template<class X, class Y> void amin(X& x, const Y& y){if(x > y) x = y;}
typedef vector<int> vi; typedef pair<int, int> ii; typedef long long ll; typedef long double ld;
const int INF = 1e9 + 10; const ll INFL = 1e18 + 10;
const int MAX = 2e5 + 10;

struct op{
    int x, y, z;
};

int n, moment, trsz;
vi es[MAX];
vector<op> res;
bool mark[MAX];
ii sz[MAX];

void add_op(const op &x){
    if(x.x == 0 || x.y == x.z) return;
    res.pb(x);
}

void add(ii &p, int value){
    if(p.se < moment) p = par(value, moment);
    else p.fi += value;
}

int dfs_centroid(int u, int p){
    for(auto v : es[u])
    if(!mark[v] && v != p && sz[v].fi > trsz/2) return dfs_centroid(v, u);
    return u;
}

void dfs_size(int u, int p){
    add(sz[u], 1);
    for(auto v : es[u]) if(!mark[v] && v != p){
        dfs_size(v, u);
        add(sz[u], sz[v].fi);
    }
}

void find_centroid(int u, int pc){
    moment++;
    dfs_size(u, 0);
    trsz = sz[u].fi;
    int x = dfs_centroid(u, 0);
    mark[x] = true;
    add_op(op{pc, u, x});
    for(auto v : es[x]) if(!mark[v]) find_centroid(v, x);
}

void process(){
    cin >> n;
    for(int i = 1; i < n; i++){
        int u, v; cin >> u >> v;
        es[u].pb(v); es[v].pb(u);
    }

    find_centroid(1, 0);
    cout << res.size() << endl;
    for(auto v : res) cout << v.x << " " << v.y << " " << v.z << endl;
}

int main(){
    ios_base::sync_with_stdio(false);
    //cin.tie(NULL);
    //freopen("c.in", "r", stdin);
    process();
}

#pragma region Macros
#pragma GCC optimize("O3")

#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i,a,b) for(ll i=a;i<=b;++i)
#define rep(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i>=b;--i)
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vec vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1,_2,name,...) name
#define vv(a,b) vector<vector<int>>(a,vector<int>(b))
#define vv2(a,b,c) vector<vector<int>>(a,vector<int>(b,c))
#define vvl(a,b) vector<vector<ll>>(a,vector<ll>(b))
#define vvl2(a,b,c) vector<vector<ll>>(a,vector<ll>(b,c))
#define vvv(a,b,c) vector<vv(b,c)>(a)
#define vvv2(a,b,c,d) vector<vv(b,c,d)>(a)
#define vvvl(a,b,c) vector<vvl(b,c)>(a)
#define vvvl2(a,b,c,d) vector<vvl(b,c,d)>(a)
#define fi first
#define se second
#define all(c) begin(c),end(c)
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define lb(c,x) distance((c).begin(),lower_bound(all(c),(x)))
#define ub(c,x) distance((c).begin(),upper_bound(all(c),(x)))
using namespace std;
template<class T> using pq = priority_queue<T>;
template<class T> using pqg = priority_queue<T,vector<T>,greater<T>>;
#define INT(...) int __VA_ARGS__;IN(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;IN(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__;IN(__VA_ARGS__)
#define STR(...) string __VA_ARGS__;IN(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__;IN(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__;IN(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__;IN(__VA_ARGS__)
#define VEC(type,name,size) vector<type> name(size);IN(name)
#define VV(type,name,h,w) vector<vector<type>>name(h,vector<type>(w));IN(name)
int scan(){ return getchar(); }
void scan(int& a){ cin>>a; }
void scan(long long& a){ cin>>a; }
void scan(char &a){cin>>a;}
void scan(double &a){ cin>>a; }
void scan(long double& a){ cin>>a; }
void scan(char a[]){ scanf("%s", a); }
void scan(string& a){ cin >> a; }
template<class T> void scan(vector<T>&);
template<class T, size_t size> void scan(array<T, size>&);
template<class T, class L> void scan(pair<T, L>&);
template<class T, size_t size> void scan(T(&)[size]);
template<class T> void scan(vector<T>& a){ for(auto& i : a) scan(i); }
template<class T> void scan(deque<T>& a){ for(auto& i : a) scan(i); }
template<class T, size_t size> void scan(array<T, size>& a){ for(auto& i : a) scan(i); }
template<class T, class L> void scan(pair<T, L>& p){ scan(p.first); scan(p.second); }
template<class T, size_t size> void scan(T (&a)[size]){ for(auto& i : a) scan(i); }
template<class T> void scan(T& a){ cin >> a; }
void IN(){}
template <class Head, class... Tail> void IN(Head& head, Tail&... tail){ scan(head); IN(tail...); }
string stin() {string s;cin>>s;return s;}
template<class T> inline bool chmax(T& a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T> inline bool chmin(T& a,T b){if(a>b){a=b;return 1;}return 0;}
vi iota(int n){vi a(n);iota(all(a),0);return a;}
template<class T> void UNIQUE(vector<T> &x){sort(all(x));x.erase(unique(all(x)),x.end());}
int in() {int x;cin>>x;return x;}
ll lin() {unsigned long long x;cin>>x;return x;}
void print(){putchar(' ');}
void print(bool a){cout<<a;}
void print(int a){cout<<a;}
void print(long long a){cout<<a;}
void print(char a){cout<<a;}
void print(string &a){cout<<a;}
void print(double a){cout<<a;}
template<class T> void print(const vector<T>&);
template<class T, size_t size> void print(const array<T, size>&);
template<class T, class L> void print(const pair<T, L>& p);
template<class T, size_t size> void print(const T (&)[size]);
template<class T> void print(const vector<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } cout<<endl;}
template<class T> void print(const deque<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } }
template<class T, size_t size> void print(const array<T, size>& a){ print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } }
template<class T, class L> void print(const pair<T, L>& p){ cout<<'(';print(p.first); cout<<","; print(p.second);cout<<')'; }
template<class T, size_t size> void print(const T (&a)[size]){ print(a[0]); for(auto i = a; ++i != end(a); ){ cout<<" "; print(*i); } }
template<class T> void print(const T& a){ cout << a; }
int out(){ putchar('\n'); return 0; }
template<class T> int out(const T& t){ print(t); putchar('\n'); return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; }
ll gcd(ll a, ll b){ while(b){ ll c = b; b = a % b; a = c; } return a; }
ll lcm(ll a, ll b){ if(!a || !b) return 0; return a * b / gcd(a, b); }
vector<pll> factor(ll x){ vector<pll> ans; for(ll i = 2; i * i <= x; i++) if(x % i == 0){ ans.push_back({i, 1}); while((x /= i) % i == 0) ans.back().second++; } if(x != 1) ans.push_back({x, 1}); return ans; }
vector<int> divisor(int x){ vector<int> ans; for(int i=1;i*i<=x;i++)if(x%i==0){ans.pb(i);if(i*i!=x)ans.pb(x/i);} return ans;}
int popcount(ll x){return __builtin_popcountll(x);}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int n){return uniform_int_distribution<int>(0, n)(rng);}
#define endl '\n'

#ifdef _LOCAL
    #undef endl
    #define debug(x) cout<<#x<<": ";print(x);cout<<endl;
    void err(){}
    template<class T> void err(const T& t){ print(t);  cout<<" ";}
    template<class Head, class... Tail> void err(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); }
#else
    #define debug(x)
    template<class... T> void err(const T&...){}
#endif
#pragma endregion

template< typename T >
struct edge{
    int from, to;
    T cost;
    edge(int to,T cost) : from(-1), to(to), cost(cost){}
    edge(int from,int to,T cost) : from(from), to(to), cost(cost){}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const{ return to;}
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedTree = vector< Edges<T>>;
using tree = vector< vector<int> >;
using UnWeightedGraph = tree;
tree make(int n,int offset = 1){
    tree res(n);
    for(int i = 0;i < n-1; i++){
        int a,b; cin >> a >> b;
        a -= offset,b -= offset;
        res[a].emplace_back(b);
        res[b].emplace_back(a);
    }
    return res;
}
template< typename T >
WeightedTree<T> make2(int n, int offset = 1){
    WeightedTree<T> res(n);
    for(int i = 0;i < n-1 ; i++){
        int a,b ; cin >> a >> b;
        a -= offset, b -= offset;
        T c; cin >> c;
        res[a].emplace_back(b,c);
        res[b].emplace_back(a,c);
    }
    return res;
}

vector<tuple<int,int,int>> ans;
template< typename G >
struct CentroidDecomposition {
  const G &g;
  vector< int > sub;
  vector< vector< int > > belong;
  vector< bool > v;

  CentroidDecomposition(const G &g) : g(g), sub(g.size()), v(g.size()), belong(g.size()) {}

  inline int build_dfs(int idx, int par) {
    sub[idx] = 1;
    for(auto &to : g[idx]) {
      if(to == par || v[to]) continue;
      sub[idx] += build_dfs(to, idx);
    }
    return sub[idx];
  }

  inline int search_centroid(int idx, int par, const int mid) {
    for(auto &to : g[idx]) {
      if(to == par || v[to]) continue;
      if(sub[to] > mid) return search_centroid(to, idx, mid);
    }
    return idx;
  }

  inline void belong_dfs(int idx, int par, int centroid) {
    belong[idx].emplace_back(centroid);
    for(auto &to : g[idx]) {
      if(to == par || v[to]) continue;
      belong_dfs(to, idx, centroid);
    }
  }

  inline int build(UnWeightedGraph &t, int idx) {
    int centroid = search_centroid(idx, -1, build_dfs(idx, -1) / 2);
    v[centroid] = true;
    belong_dfs(centroid, -1, centroid);
    for(auto &to : g[centroid]) {
      if(!v[to]) {
          t[centroid].emplace_back(build(t, to));
          ans.eb(centroid,to,t[centroid].back());
      }
    }
    v[centroid] = false;
    return centroid;
  }

  inline int build(UnWeightedGraph &t) {
    t.resize(g.size());
    return build(t, 0);
  }
};

signed main(){
    // ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);cout<<fixed<<setprecision(15);
    INT(n);
    tree g = make(n);
    CentroidDecomposition CD(g);
    tree t;
    CD.build(t);
    cout << ans.size()<<endl;
    for(auto [a,b,c]:ans){
        cout<<++a<<" "<<++b<<" "<<++c<<endl;
    }
}

// E
#include <bits/stdc++.h>

#define SQ(a) (a)*(a)

#define F0R(i, a) for(int i = 0; i < (a); i++)
#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define R0F(i, a) for(int i = (a) - 1; i >= 0; i--)
#define ROF(i, a, b) for(int i = (b) - 1; i >= (a); i--)

#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define UB upper_bound
#define LB lower_bound
#define X real()
#define Y imag()
#define MAXN 200000

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef complex<ll> point;

int n;
bool isCentroid[MAXN];
unordered_set<int> connections[MAXN];
vector<tuple<int, int, int>> transformations;

int sizeOfTree(int node, int par) {
    int total = 1;
    for(const int conn : connections[node]) {
        if(conn != par && !isCentroid[conn]) total += sizeOfTree(conn, node);
    }
    return total;
}

int centroidDecompose(int node) {
    vector<pii> childrenSizes;
    int total = 1;
    for(const int conn : connections[node]) {
        if(!isCentroid[conn]) {
            childrenSizes.PB(MP(sizeOfTree(conn, node), conn));
            total+=childrenSizes[childrenSizes.size() - 1].F;
        }
    }
    for(const pii sizeOfChild : childrenSizes) {
        if(sizeOfChild.F > total / 2) return centroidDecompose(sizeOfChild.S);
    }
    isCentroid[node] = true;
    for(const pii sizeOfChild : childrenSizes) {
        int centroid = centroidDecompose(sizeOfChild.S);
        if(centroid != sizeOfChild.S) {
            transformations.PB(MT(node, sizeOfChild.S, centroid));
            connections[node].erase(sizeOfChild.S);
            connections[node].insert(centroid);
            connections[sizeOfChild.S].erase(node);
            connections[centroid].insert(node);
        }
    }
    return node;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    F0R(i, n - 1) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        connections[a].insert(b), connections[b].insert(a);
    }
    centroidDecompose(0);
    cout << transformations.size() << "\n";
    for(const tuple<int, int, int> t: transformations) cout << get<0>(t) + 1 << " " << get<1>(t) + 1 << " " << get<2>(t) + 1 << "\n";
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

const int N = 1234567;

vector <int> st;
int pv[N], sz[N];
vector <int> g[N];
vector <int> jobs[N];
int depth[N];

bool flag;

void dfs(int v, int pr) {
  st.push_back(v);
  pv[v] = pr;
  sz[v] = 1;
  for (int u : g[v]) {
    if (u == pr) {
      continue;
    }
    depth[u] = depth[v] + 1;
    dfs(u, v);
    sz[v] += sz[u];
  }
  if (flag && depth[v] >= 3) {
    jobs[st[1]].push_back(v);
  }
  st.pop_back();
}

int main() {
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n - 1; i++) {
    int x, y;
    scanf("%d %d", &x, &y);
    x--; y--;
    g[x].push_back(y);
    g[y].push_back(x);
  }
  flag = false;
  dfs(0, -1);
  vector <int> roots;
  for (int i = 0; i < n; i++) {
    int outer = n - sz[i];
    if (outer > n / 2) {
      continue;
    }
    bool ok = true;
    for (int j : g[i]) {
      if (j == pv[i]) {
        continue;
      }
      if (sz[j] > n / 2) {
        ok = false;
        break;
      }
    }
    if (ok) {
      roots.push_back(i);
    }
  }
  assert(!roots.empty());
  flag = true;
  if ((int) roots.size() == 1) {
    depth[roots[0]] = 0;
    dfs(roots[0], -1);
  } else {
    depth[roots[0]] = depth[roots[1]] = 1;
    st.push_back(roots[1]);
    dfs(roots[0], roots[1]);
    st.pop_back();
    st.push_back(roots[0]);
    dfs(roots[1], roots[0]);
    st.pop_back();
  }
  vector < pair <int, pair <int, int> > > res;
  for (int i = 0; i < n; i++) {
    if (jobs[i].empty()) {
      continue;
    }
    int at = i;
    for (int &v : jobs[i]) {
      res.emplace_back(pv[i], make_pair(at, v));
      res.emplace_back(v, make_pair(pv[v], i));
      at = v;
    }
    res.emplace_back(pv[i], make_pair(at, i));
  }
  int cnt = res.size();
  printf("%d\n", cnt);
  for (int i = 0; i < cnt; i++) {
    printf("%d %d %d\n", res[i].first + 1, res[i].second.first + 1, res[i].second.second + 1);
  }
  return 0;
}

#include "bits/stdc++.h"
using namespace std;
const int maxn = 202020;
vector<int> tr[maxn];
int sz[maxn], par[maxn], dep[maxn];
void dfs(int cur, int pr){
	par[cur] = pr;
	sz[cur] = 1;
	for(int nxt : tr[cur]){
		if(nxt == pr) continue;
		dep[nxt] = dep[cur] + 1;
		dfs(nxt, cur);
		sz[cur] += sz[nxt];
	}
}
vector<tuple<int,int,int> > o;
void build(int cur, int pr, int d){
	par[cur] = pr;
	if(d >= 2){
		o.push_back(make_tuple(cur, pr, par[pr]));
		par[cur] = par[pr];
	}
	for(int nxt : tr[cur]){
		if(nxt == pr) continue;
		build(nxt, cur, d + 1);
	}
}
int main(){
	int n;
	scanf("%d", &n);
	for(int e = 0; e < n - 1; e++){
		int u, v;
		scanf("%d %d", &u, &v);
		tr[u].push_back(v);
		tr[v].push_back(u);
	}
	dfs(1, 0);
	vector<int> cen;
	for(int e = 1; e <= n; e++){
		int mx = n - sz[e];
		for(int nxt : tr[e]){
			if(nxt == par[e]) continue;
			mx = max(mx, sz[nxt]);
		}
		if(mx <= n / 2) cen.push_back(e);
	}
	if(cen.size() == 1){
		build(cen[0], 0, 0);
	} else {
		build(cen[0], cen[1], 0);
		build(cen[1], cen[0], 0);
	}
	printf("%d\n", (int)o.size());
	for(auto e : o){
		int u, v, w;
		tie(u, v, w) = e;
		printf("%d %d %d\n", v, u, w);
	}
	return 0;
}

#pragma region Macros
#pragma GCC optimize("O3")

#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i,a,b) for(ll i=a;i<=b;++i)
#define rep(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i>=b;--i)
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vec vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1,_2,name,...) name
#define vv(a,b) vector<vector<int>>(a,vector<int>(b))
#define vv2(a,b,c) vector<vector<int>>(a,vector<int>(b,c))
#define vvl(a,b) vector<vector<ll>>(a,vector<ll>(b))
#define vvl2(a,b,c) vector<vector<ll>>(a,vector<ll>(b,c))
#define vvv(a,b,c) vector<vv(b,c)>(a)
#define vvv2(a,b,c,d) vector<vv(b,c,d)>(a)
#define vvvl(a,b,c) vector<vvl(b,c)>(a)
#define vvvl2(a,b,c,d) vector<vvl(b,c,d)>(a)
#define fi first
#define se second
#define all(c) begin(c),end(c)
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define lb(c,x) distance((c).begin(),lower_bound(all(c),(x)))
#define ub(c,x) distance((c).begin(),upper_bound(all(c),(x)))
using namespace std;
template<class T> using pq = priority_queue<T>;
template<class T> using pqg = priority_queue<T,vector<T>,greater<T>>;
#define INT(...) int __VA_ARGS__;IN(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;IN(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__;IN(__VA_ARGS__)
#define STR(...) string __VA_ARGS__;IN(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__;IN(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__;IN(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__;IN(__VA_ARGS__)
#define VEC(type,name,size) vector<type> name(size);IN(name)
#define VV(type,name,h,w) vector<vector<type>>name(h,vector<type>(w));IN(name)
int scan(){ return getchar(); }
void scan(int& a){ cin>>a; }
void scan(long long& a){ cin>>a; }
void scan(char &a){cin>>a;}
void scan(double &a){ cin>>a; }
void scan(long double& a){ cin>>a; }
void scan(char a[]){ scanf("%s", a); }
void scan(string& a){ cin >> a; }
template<class T> void scan(vector<T>&);
template<class T, size_t size> void scan(array<T, size>&);
template<class T, class L> void scan(pair<T, L>&);
template<class T, size_t size> void scan(T(&)[size]);
template<class T> void scan(vector<T>& a){ for(auto& i : a) scan(i); }
template<class T> void scan(deque<T>& a){ for(auto& i : a) scan(i); }
template<class T, size_t size> void scan(array<T, size>& a){ for(auto& i : a) scan(i); }
template<class T, class L> void scan(pair<T, L>& p){ scan(p.first); scan(p.second); }
template<class T, size_t size> void scan(T (&a)[size]){ for(auto& i : a) scan(i); }
template<class T> void scan(T& a){ cin >> a; }
void IN(){}
template <class Head, class... Tail> void IN(Head& head, Tail&... tail){ scan(head); IN(tail...); }
string stin() {string s;cin>>s;return s;}
template<class T> inline bool chmax(T& a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T> inline bool chmin(T& a,T b){if(a>b){a=b;return 1;}return 0;}
vi iota(int n){vi a(n);iota(all(a),0);return a;}
template<class T> void UNIQUE(vector<T> &x){sort(all(x));x.erase(unique(all(x)),x.end());}
int in() {int x;cin>>x;return x;}
ll lin() {unsigned long long x;cin>>x;return x;}
void print(){putchar(' ');}
void print(bool a){cout<<a;}
void print(int a){cout<<a;}
void print(long long a){cout<<a;}
void print(char a){cout<<a;}
void print(string &a){cout<<a;}
void print(double a){cout<<a;}
template<class T> void print(const vector<T>&);
template<class T, size_t size> void print(const array<T, size>&);
template<class T, class L> void print(const pair<T, L>& p);
template<class T, size_t size> void print(const T (&)[size]);
template<class T> void print(const vector<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } cout<<endl;}
template<class T> void print(const deque<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } }
template<class T, size_t size> void print(const array<T, size>& a){ print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } }
template<class T, class L> void print(const pair<T, L>& p){ cout<<'(';print(p.first); cout<<","; print(p.second);cout<<')'; }
template<class T, size_t size> void print(const T (&a)[size]){ print(a[0]); for(auto i = a; ++i != end(a); ){ cout<<" "; print(*i); } }
template<class T> void print(const T& a){ cout << a; }
int out(){ putchar('\n'); return 0; }
template<class T> int out(const T& t){ print(t); putchar('\n'); return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; }
ll gcd(ll a, ll b){ while(b){ ll c = b; b = a % b; a = c; } return a; }
ll lcm(ll a, ll b){ if(!a || !b) return 0; return a * b / gcd(a, b); }
vector<pll> factor(ll x){ vector<pll> ans; for(ll i = 2; i * i <= x; i++) if(x % i == 0){ ans.push_back({i, 1}); while((x /= i) % i == 0) ans.back().second++; } if(x != 1) ans.push_back({x, 1}); return ans; }
vector<int> divisor(int x){ vector<int> ans; for(int i=1;i*i<=x;i++)if(x%i==0){ans.pb(i);if(i*i!=x)ans.pb(x/i);} return ans;}
int popcount(ll x){return __builtin_popcountll(x);}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int n){return uniform_int_distribution<int>(0, n)(rng);}
#define endl '\n'

#ifdef _LOCAL
    #undef endl
    #define debug(x) cout<<#x<<": ";print(x);cout<<endl;
    void err(){}
    template<class T> void err(const T& t){ print(t);  cout<<" ";}
    template<class Head, class... Tail> void err(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); }
#else
    #define debug(x)
    template<class... T> void err(const T&...){}
#endif
#pragma endregion

template< typename T >
struct edge{
    int from, to;
    T cost;
    edge(int to,T cost) : from(-1), to(to), cost(cost){}
    edge(int from,int to,T cost) : from(from), to(to), cost(cost){}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const{ return to;}
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedTree = vector< Edges<T>>;
using tree = vector< vector<int> >;
using UnWeightedGraph = tree;
tree make(int n,int offset = 1){
    tree res(n);
    for(int i = 0;i < n-1; i++){
        int a,b; cin >> a >> b;
        a -= offset,b -= offset;
        res[a].emplace_back(b);
        res[b].emplace_back(a);
    }
    return res;
}
template< typename T >
WeightedTree<T> make2(int n, int offset = 1){
    WeightedTree<T> res(n);
    for(int i = 0;i < n-1 ; i++){
        int a,b ; cin >> a >> b;
        a -= offset, b -= offset;
        T c; cin >> c;
        res[a].emplace_back(b,c);
        res[b].emplace_back(a,c);
    }
    return res;
}

signed main(){
    // ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);cout<<fixed<<setprecision(15);
    INT(n);
    tree g = make(n);
    vector<int> sub(n);
    int centroid;
    vector<int> centroids;
    {
        auto dfs = [&](auto &&f,int x,int p)->int{
            sub[x] = 1;
            for(auto e:g[x]) if(e!=p) sub[x] += f(f,e,x);
            return sub[x];
        };
        dfs(dfs,0,-1);
        auto search = [&](auto &&f,int x,int p)->int{
            for(auto e:g[x]){
                if(e == p) continue;
                if(sub[e] > n/2) return f(f,e,x);
            }
            return x;
        };
        centroid = search(search,0,-1);
        dfs(dfs,centroid,-1);
        rep(i,n) if(~n&1 and sub[i] == n/2) centroids.eb(i);
        centroids.eb(centroid);
    }
    vector<int> top(n),tail(n);
    vector<tuple<int,int,int>> ans;
    auto dfs = [&](auto &&f,int x,int p,int c,int cc)->void{
        if(p!=c and p!= cc){
            ans.eb(c,cc,x);
            ans.eb(x,p,cc);
            ans.eb(c,x,cc);
        }
        for(auto e:g[x]) if(e != p) f(f,e,x,c,cc);
        return ;
    };
    vector<bool> ng(n);
    for(auto c:centroids) ng[c] = true;
    for(auto c:centroids){
        for(auto cc:g[c]){
            if(!ng[cc])
            dfs(dfs,cc,c,c,cc);
        }
    }
    vector<tuple<int,int,int>> ANS;
    rep(i,ans.size()){
        if(i < ans.size()-1 and ans[i] == ans[i+1]){
            i++;continue;
        }
        ANS.eb(ans[i]);
    }
    cout << ANS.size() << endl;
    for(auto [a,b,c] :ANS){
        cout << ++ a << " " << ++ b << " " << ++ c << endl;
    }

}

#include <cstdio>
#include <iostream>
#include <vector>
#define travel(x, i) for (int i = fir[x]; i; i = e[i].nxt)
using namespace std;

const int N = 2e5 + 5;

struct node{
  int a, b, c;
};
struct edge {
  int nxt, to;
}e[N << 1];
int fir[N], cnt = 0, n;
int size[N], rt, minson = 2e9;
vector <node> ans;

inline void add(int x, int y) {
  e[++ cnt] = (edge){fir[x], y};
  fir[x] = cnt;
}

inline void find_rt(int x, int pa) {
  size[x] = 1;
  int maxson = 0;
  travel(x, i)
    if (e[i].to != pa) {
      find_rt(e[i].to, x);
      size[x] += size[e[i].to];
      maxson = max(maxson, size[e[i].to]);
    }
  maxson = max(maxson, n - size[x]);
  if (maxson < minson) {
    rt = x;
    minson = maxson;
  }
}

inline void getsz(int x, int pa) {
  size[x] = 1;
  travel(x, i)
    if (e[i].to != pa) {
      getsz(e[i].to, x);
      size[x] += size[e[i].to];
    }
}

inline void dfs(int x, int pa, int anc, int rt) {
  travel(x, i)
    if (e[i].to != pa) dfs(e[i].to, x, anc, rt);
  if (x != anc) ans.push_back((node){rt, anc, x});
  if (pa != rt) ans.push_back((node){x, pa, rt});
}

inline void getans(int x, int forbid) {
  travel(x, i)
    if (e[i].to != forbid) dfs(e[i].to, x, e[i].to, x);
}

int main() {
  int x, y;
  scanf("%d", &n);
  for (int i = 1; i < n; i ++) {
    scanf("%d%d", &x, &y);
    add(x, y); add(y, x);
  }
  find_rt(1, 0);
  getsz(rt, 0);
  int big_son = 0;
  travel(rt, i)
    if (size[e[i].to] * 2 == n) big_son = e[i].to;
  if (!big_son) getans(rt, 0);
  else {
    getans(rt, big_son);
    getans(big_son, rt);
  }
  printf("%d\n", (int)ans.size());
  for (int i = 0; i < (int)ans.size(); i ++) printf("%d %d %d\n", ans[i].a, ans[i].b, ans[i].c);
  return 0;
}

// author: gary
#include <bits/stdc++.h>
using namespace std;
#define SZ(x) ( (int) (x).size() )
const int N = 2e5 + 10;

int n;
vector<int> E[N];

int sz[N];
int is_centroid[N];
vector<int> centroids;

struct job { int x, y, z; };
vector<job> jobs;

int dfs1(int u, int pv) {
  sz[u] = 1;
  for(int v: E[u]) {
    if(v != pv) {
      sz[u] += dfs1(v, u);
    }
  }

  is_centroid[u] = sz[u] * 2 > n;
  for(int v: E[u]) {
    if(v != pv) {
      is_centroid[u] &= n - sz[v] > sz[v];
    }
  }

  if(is_centroid[u]) {
    centroids.push_back(u);
  }

  return sz[u];
}

vector<int> post_order;
int p[N];

void dfs2(int u, int pv) {
  p[u] = pv;
  for(int v: E[u]) {
    if(pv != v) {
      dfs2(v, u);
    }
  }
  post_order.push_back(u);
}

void add_job(int a, int b, int c) {
  jobs.push_back({a, b, c});
}

void flatten(int c, int r) {
  add_job(c, r, post_order[0]);
  r = post_order[0];
  for(int u: post_order) {
    if(u == r)
      continue;
    add_job(r, p[r], u);
    r = p[r];
  }
}

void star_graph(int center) {
  int s = SZ(post_order);
  if(s >= 3) {
    for(int i = s - 4; i >= 0; i--) {
      add_job(post_order[i], post_order[i + 1], post_order[s - 2]);
    }
    add_job(center, post_order[0], post_order[s - 2]);
  }
}

int main() {
  scanf("%d", &n);
  for(int i = 0; i < n - 1; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    E[u].push_back(v);
    E[v].push_back(u);
  }

  dfs1(1, -1);

  for(int centroid: centroids) {
    cerr << "centroid = " << centroid << endl;
    for(int v: E[centroid]) {
      if(!is_centroid[v]) {
        post_order.clear();
        dfs2(v, centroid);
        flatten(centroid, v);
        star_graph(centroid);
      }
    }
  }

  assert(SZ(jobs) <= 2*n);
  printf("%d\n", SZ(jobs));
  for(auto t: jobs) {
    printf("%d %d %d\n", t.x, t.y, t.z);
  }
  return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef double D;
typedef long long int LL;

#define st first
#define nd second
#define pb push_back
#define PLL pair <LL, LL>
#define PII pair <int, int>
#define PIII pair <PII, int>

const int N = 2e5 + 7;
const int MX = 1e9 + 7;
const int inf = 1e9 + 9;

int n, m;
int pod[N];
bool block[N];
vector <int> G[N];
vector <PIII> res;

int dfs(int u, int p){
	pod[u] = 1;
	for(int v: G[u])
		if(v != p && !block[v])
			pod[u] += dfs(v, u);
	return pod[u];
}

PII centroid(int u){
	dfs(u, u);
	int par = u;
	int half = (pod[u] + 1) / 2;
	bool even = (pod[u] & 1) ? 0 : 1;

	bool change = true;
	while(change){
		change = false;
		for(int v: G[u])
			if(pod[v] >= half && !block[v] && v != par){
				change = true;
				par = u;
				u = v;
				break;
			}
	}

	if(pod[u] == half && even)
		return {u, par};
	return {u, -1};
}

void add(vector <PIII> &cur, vector <PIII> plus){
	for(auto v: plus)
		cur.pb(v);
}

vector <PIII> Rozbicie(int u, int p){
	PII cur = centroid(u);
//	printf("%d %d -> %d %d\n", u, p, cur.st, cur.nd);
	if(cur.nd == -1){
		vector <PIII> ret;
		block[cur.st] = true;

		if(p != -1 && u != cur.st)
			ret.pb({{p, u}, cur.st});

		for(int v: G[cur.st]){
			if(block[v])	continue;
			add(ret, Rozbicie(v, cur.st));
		}

		return ret;
	}
	else{
		block[cur.st] = true;
		vector <PIII> ret = Rozbicie(u, p);
		block[cur.st] = false;
		add(ret, Rozbicie(cur.st, ret.size() == 0 ? u : ret[0].nd));
		return ret;
	}
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i < n; ++i){
		int u, v;
		scanf("%d %d", &u, &v);
		G[u].pb(v);
		G[v].pb(u);
	}

	res = Rozbicie(1, -1);
	printf("%d\n", (int)res.size());
	for(int i = 0; i < (int)res.size(); ++i)
		printf("%d %d %d\n", res[i].st.st, res[i].st.nd, res[i].nd);
	return 0;
}

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

#define N 202020

int n, sos[N], pa[N];

vector<int> v[N], u[N];

void dfs(int rt) {
	if (rt != 1 && v[rt].size() == 1) {
		sos[rt] = 1;
		return;
	}
	sos[rt] = 1;
    for (int i = 0; i < v[rt].size(); i ++) if (v[rt][i] != pa[rt]) {
		pa[v[rt][i]] = rt;
		dfs(v[rt][i]);
		sos[rt] += sos[v[rt][i]];
    }
}

int cnt;
int ansx[N*2], ansy[N*2], ansz[N*2];

void putans() {
	printf("%d\n", cnt);
	for (int i = 1; i <= cnt; i ++) printf("%d %d %d\n", ansx[i], ansy[i], ansz[i]);
}

void oper(int x, int y, int z) {
	ansx[++cnt] = x;
	ansy[cnt] = y;
	ansz[cnt] = z;
}

int curx[N], cury[N];
int q[N];

bool ok(int rt) {
	if (sos[rt] * 2 <= n) return 0;
	for (int i = 0; i < v[rt].size(); i ++) if (v[rt][i] != pa[rt]) {
		if (sos[v[rt][i]] * 2 >= n) return 0;
	}
	return 1;
}

void DFS(int rt) {
    for (int i = 0; i < v[rt].size(); i ++) if (v[rt][i] != pa[rt]) {
		pa[v[rt][i]] = rt;
		DFS(v[rt][i]);
    }
}

void bfs(int rt, int wi) {
	int e = 0;
	q[++e] = rt;
	for (int f = 1; f <= e; f ++) {
		for (int i = 0; i < v[q[f]].size(); i ++) if (pa[q[f]] != v[q[f]][i]) {
			q[++e] = v[q[f]][i];
		}
	}
	int now = rt;
	for (int i = 2; i <= e; i ++) {
		oper(wi, now, q[i]);
		now = q[i];
		oper(now, pa[now], rt);
	}
	oper(wi, now, rt);
}

void solve(int rt) {
	memset(pa, 0, sizeof pa);
	DFS(rt);
	for (int i = 0; i < v[rt].size(); i ++) {
        bfs(v[rt][i], rt);
	}
}

void bfs1(int rt) {
	int e = 0;
	q[++e] = rt;
	for (int f = 1; f <= e; f ++) {
		for (int i = 0; i < v[q[f]].size(); i ++) if (pa[q[f]] != v[q[f]][i]) {
			q[++e] = v[q[f]][i];
		}
	}
	int to = q[2];
	int now = to;
	for (int i = 3; i <= e; i ++) {
		if (pa[q[i]] == rt) continue;
		oper(rt, now, q[i]);
		now = q[i];
		oper(now, pa[q[i]], to);
	}
	oper(rt, now, to);
}

void new_solve(int rt, int rt2) {
	memset(pa, 0, sizeof pa);
	pa[rt] = rt2;
	pa[rt2] = rt;
	DFS(rt);
	DFS(rt2);
	bfs1(rt);
	bfs1(rt2);
}

int main() {
	scanf("%d", &n);
	for (int i = 1, x, y; i < n; i ++) {
		scanf("%d %d", &x, &y);
		v[x].push_back(y);
		v[y].push_back(x);
	}
	if (n <= 4) {
		puts("0");
		return 0;
	}
	pa[1] = 0;
	dfs(1);
	bool flag = 0;
	for (int i = 1; i <= n && !flag; i ++) {
		if (ok(i)) {
			solve(i);
			flag = 1;
		}
	}
	if (!flag) {
		for (int i = 1; i <= n && !flag; i ++) {
            if (sos[i] * 2 == n) {
				new_solve(i, pa[i]);
				flag = 1;
            }
		}
	}
	assert(flag);
	putans();
	return 0;
}

// E
#include <bits/stdc++.h>

#define SQ(a) (a)*(a)

#define F0R(i, a) for(int i = 0; i < (a); i++)
#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define R0F(i, a) for(int i = (a) - 1; i >= 0; i--)
#define ROF(i, a, b) for(int i = (b) - 1; i >= (a); i--)

#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define UB upper_bound
#define LB lower_bound
#define X real()
#define Y imag()
#define MAXN 200000

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef complex<ll> point;

int n;
bool isCentroid[MAXN];
vi connections[MAXN];
vector<tuple<int, int, int>> transformations;

int sizeOfTree(int node, int par) {
    int total = 1;
    for(const int conn : connections[node]) {
        if(conn != par && !isCentroid[conn]) total += sizeOfTree(conn, node);
    }
    return total;
}

int centroidDecompose(int node) {
    vector<pii> childrenSizes;
    int total = 1;
    for(const int conn : connections[node]) {
        if(!isCentroid[conn]) {
            childrenSizes.PB(MP(sizeOfTree(conn, node), conn));
            total+=childrenSizes[childrenSizes.size() - 1].F;
        }
    }
    for(const pii sizeOfChild : childrenSizes) {
        if(sizeOfChild.F > total / 2) return centroidDecompose(sizeOfChild.S);
    }
    isCentroid[node] = true;
    vector<pii> centroids;
    for(const pii sizeOfChild : childrenSizes) {
        centroids.PB(MP(centroidDecompose(sizeOfChild.S), sizeOfChild.S));
    }
    F0R(i, childrenSizes.size()) {
        if(childrenSizes[i].F < total - childrenSizes[i].F && centroids[i].S != centroids[i].F) {
            transformations.PB(MT(node, centroids[i].S, centroids[i].F));
        }
    }
    return node;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    F0R(i, n - 1) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        connections[a].PB(b), connections[b].PB(a);
    }
    centroidDecompose(0);
    if(transformations.size() > 2 * n) return 1;
    cout << transformations.size() << "\n";
    for(const tuple<int, int, int> t: transformations) cout << get<0>(t) + 1 << " " << get<1>(t) + 1 << " " << get<2>(t) + 1 << "\n";
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

const int INF = (int) 1e9 + 123;
const ll LINF = (ll) 1e18 + 123;
const ld EPS = (ld) 1e-12;
const ll MOD = (ll) 1e9 + 7;

#define sz(x) (int) (x).size()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define lb(s, t, x) (int) (lower_bound(s, t, x) - s)
#define ub(s, t, x) (int) (upper_bound(s, t, x) - s)
#define rep(i, f, t) for (auto i = f; i < t; i++)
#define per(i, f, t) for (auto i = f; i >= t; i--)

ll power(ll x, ll y, ll mod = MOD) {
    if (y == 0) {
        return 1;
    }
    if (y & 1) {
        return power(x, y - 1, mod) * x % mod;
    } else {
        ll tmp = power(x, y / 2, mod);
        return tmp * tmp % mod;
    }
}

inline void add(ll &x, ll y, ll mod = MOD) {
    x += y;
    if (x >= mod) x -= mod;
    if (x < 0) x += mod;
}

inline ll sum(ll x, ll y, ll mod = MOD) {
    add(x, y, mod);
    return x;
}

inline ll mult(ll x, ll y, ll mod = MOD) {
    return (x * y) % mod;
}

inline ll div(ll x, ll y, ll mod) {
    return x * power(y, mod - 2, mod);
}

template<typename A, typename B> inline bool mini(A &x, const B &y) {
    if (y < x) {
        x = y;
        return true;
    }
    return false;
}

template<typename A, typename B> inline bool maxi(A &x, const B &y) {
    if (y > x) {
        x = y;
        return true;
    }
    return false;
}

template<typename T> inline void read(T first, T last) {
    while (first != last) {
        cin >> *(first++);
    }
}

template<typename T> inline void print(T first, T last) {
    while (first != last) {
        cout << *(first++) << " ";
    }
    cout << "\n";
}

void run();

#define TASK ""

int main() {
#ifdef LOCAL
    if (strlen(TASK) > 0) {
        cerr << "Reminder: you are using file i/o, filename: " TASK "!" << endl << endl;
    }
#endif
#ifndef LOCAL
    if (strlen(TASK)) {
        freopen(TASK ".in", "r", stdin);
        freopen(TASK ".out", "w", stdout);
    }
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif
    cout << fixed << setprecision(12);
    run();
    return 0;
}

// == SOLUTION == //

const int N = (int) 2e5 + 123;

struct Q {
    int x, y1, y2;
};

int n;
vector<pair<int, int>> g[N];
vector<Q> res;
bool vis[N], used[N];
int cnt[N];

void calc_cnt(int v, int p = -1) {
    cnt[v] = 1;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || u == p || used[e.second]) continue;
        calc_cnt(u, v);
        cnt[v] += cnt[u];
    }
}

int dfs(int v);

pair<bool, int> centroid_edge(int v, int all, int p = -1) {
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || u == p || used[e.second]) continue;
        auto tmp = centroid_edge(u, all, v);
        if (tmp.first) return tmp;
        if (2 * cnt[u] == all) {
            used[e.second] = 1;
            dfs(v);
            dfs(u);
            return {1, u};
        }
    }
    return {0, -1};
}

void find_centroid(int v, int all, int &x, int p = -1) {
    bool ok = 1;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || used[e.second]) continue;
        ok &= 2 * (u != p ? cnt[u] : all - cnt[v]) < all;
        if (u == p) continue;
        find_centroid(u, all, x, v);
    }
    if (ok) {
        assert(x == -1);
        x = v;
    }
}

int dfs(int v) {
    calc_cnt(v);
    auto tmp = centroid_edge(v, cnt[v]);
    if (tmp.first) {
        return tmp.second;
    }

    int centroid = -1;
    find_centroid(v, cnt[v], centroid);
    assert(centroid != -1);
    v = centroid;
    vis[v] = 1;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || used[e.second]) continue;
        int t = dfs(u);
        if (u != t) res.push_back({v, u, t});
    }
    return v;
}

void run() {
    cin >> n;
    rep(i, 0, n - 1) {
        int u, v;
        cin >> u >> v;
        g[u].pb({v, i});
        g[v].pb({u, i});
    }

    dfs(1);

    cout << sz(res) << "\n";
    for (Q &q : res) {
        cout << q.x << " " << q.y1 << " " << q.y2 << "\n";
    }
}

#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.1,sse4.2,popcnt,abm,mmx,avx,tune=native")
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <assert.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define PB push_back
#define MP make_pair
const int MOD=1000000007;
#define endl "\n"
#define fst first
#define snd second
const ll UNDEF = -1;
const ll INF=1e18;
template<typename T> inline bool chkmax(T &aa, T bb) { return aa < bb ? aa = bb, true : false; }
template<typename T> inline bool chkmin(T &aa, T bb) { return aa > bb ? aa = bb, true : false; }
typedef pair<ll,ll> pll;
typedef vector<ll> vll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
#define DEBUG_CAT
#ifdef DEBUG_CAT

#define dbg(...)   printf( __VA_ARGS__ )
#else
#define dbg(...)   /****nothing****/
#endif
static char stdinBuffer[1024];
static char* stdinDataEnd = stdinBuffer + sizeof (stdinBuffer);
static const char* stdinPos = stdinDataEnd;

void readAhead(size_t amount)
{
    size_t remaining = stdinDataEnd - stdinPos;
    if (remaining < amount) {
       memmove(stdinBuffer, stdinPos, remaining);
       size_t sz = fread(stdinBuffer + remaining, 1, sizeof (stdinBuffer) - remaining, stdin);
       stdinPos = stdinBuffer;
       stdinDataEnd = stdinBuffer + remaining + sz;
       if (stdinDataEnd != stdinBuffer + sizeof (stdinBuffer))
         *stdinDataEnd = 0;
    }
}

int rint()
{
    readAhead(16);

    int x = 0;
    bool neg = false;
    while(*stdinPos==' '||*stdinPos=='\n') ++stdinPos;
    if (*stdinPos == '-') {
       ++stdinPos;
       neg = true;
    }

    while (*stdinPos >= '0' && *stdinPos <= '9') {
       x *= 10;
       x += *stdinPos - '0';
       ++stdinPos;
    }

    return neg ? -x : x;
}
char rch()
{
    readAhead(16);
    while(*stdinPos==' '||*stdinPos=='\n') ++stdinPos;
    char ans=*stdinPos;
    ++stdinPos;
    return ans;
}
long long rlong()
{
    readAhead(32);

    long long x = 0;
    bool neg = false;
    while(*stdinPos==' '||*stdinPos=='\n') ++stdinPos;
    if (*stdinPos == '-') {
       ++stdinPos;
       neg = true;
    }

    while (*stdinPos >= '0' && *stdinPos <= '9') {
       x *= 10;
       x += *stdinPos - '0';
       ++stdinPos;
    }

    return neg ? -x : x;
}

const int mn=2e5+2;
vector<int> g[mn];
bool iscentroid[mn];
vi gfoundCentroid;
int getCentroid(int u,int p,int n) {
    int cnt = 1;
    bool goodCenter = true;
    for (auto v : g[u]) {
      if (v == p||iscentroid[v]) continue;
      int size = getCentroid(v, u, n);
      goodCenter &= size <= n / 2;
      cnt += size;
    }
    goodCenter &= n - cnt <= n / 2;
    if (goodCenter) gfoundCentroid.PB(u);
    return cnt;
  }
int getSubtreeSize(int x,int p) {
  int selfSubtreeSize=1;
  for (auto &y:g[x]) {
    if (y==p||iscentroid[y]) continue;
    int childSubtreeSize=getSubtreeSize(y,x);
    selfSubtreeSize+=childSubtreeSize;
  }
  return selfSubtreeSize;
}
vector<pair<int,pii> > vfinal;
/* Custom functions end here */
void fullCentroidDecomposition(int initv,int p,int n) {
  getCentroid(initv,p,n);
  vi foundCentroid=gfoundCentroid;
  gfoundCentroid.clear();
  if (foundCentroid.size()>0) {
    int x=p;
    int y=initv;
    int yp=foundCentroid[0];
    if (x!=-1&&y!=yp) vfinal.PB(MP(x,MP(y,yp)));
  }
  vector<pii> subtreeRootsWithSizes[2];
  int allsize=0;
  for (auto &centroid:foundCentroid) iscentroid[centroid]=true;
  for (int centroidIdx=0;centroidIdx<foundCentroid.size();centroidIdx++) {
    int centroid=foundCentroid[centroidIdx];
    //printf("centroid:%d initv:%d p:%d\n",centroid,initv,p);
    for (auto &y:g[centroid]) {
      if (y!=p&&(!iscentroid[y])) {
        int sz=getSubtreeSize(y,centroid);
        //printf("centroid:%d y:%d\n",centroid,y);
        allsize+=sz;
        subtreeRootsWithSizes[centroidIdx].PB(MP(y,sz));
      }
    }
  }
  //for (auto &centroid:foundCentroid) iscentroid[centroid]=false;
  /* Custom code starts here. Should take linear time. Do not consider nodes with iscentroid=true, or nodes beyond them.*/

  /* Custom code ends here. Continue decomposing subtree.*/
  //for (auto &centroid:foundCentroid) iscentroid[centroid]=true;
  for (int centroidIdx=0;centroidIdx<foundCentroid.size();centroidIdx++) {
    int centroid=foundCentroid[centroidIdx];
    for (auto &got:subtreeRootsWithSizes[centroidIdx]) {
      int y=got.fst,sz=got.snd;
      fullCentroidDecomposition(y,centroid,sz);
    }
  }
}

int main()
{
  ios_base::sync_with_stdio(false); cin.tie(0);
  int n=rint();
  for (int i=0;i<n-1;i++) {
    int u=rint(),v=rint();
    g[u].PB(v); g[v].PB(u);
  }
  fullCentroidDecomposition(1,-1,n);
  printf("%d\n",(int)vfinal.size());
  for (auto &w:vfinal) {
    printf("%d %d %d\n",w.fst,w.snd.fst,w.snd.snd);
  }
}

#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
int N, M;
vector <int> G[200005];
int Sz[200005], Size[200005];
int sum, cnt;
bool Blocked[200005];
struct Solution{
int x, y, y2;
} S[200005];
bool first;
void Read()
{
    scanf("%d", &N);
    for(int i = 2; i <= N; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
}

void DFS(int node, int father)
{
    Sz[node] = 1;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        DFS(neighb, node);
        Sz[node] += Sz[neighb];
    }
}

int findCentroid(int node, int father, int size)
{
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        if(Sz[neighb] > size / 2)
            return findCentroid(neighb, node, size);
    }
    return node;
}

int centroidDecompose(int root)
{
    DFS(root, 0);
    int center = findCentroid(root, 0, Sz[root]);
    Blocked[center] = 1;
    int sz = Sz[root];
    bool ok = 0;
    if(first == 0)
    {
        for(int i = 1; i <= N; i++)
        Size[i] = Sz[i];
        first = 1;
        ok = 1;
    }

    int node = center;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(Blocked[neighb] == 1)
            continue;
        int n = centroidDecompose(neighb);
        if(n == neighb || (ok == 1 && Size[neighb] == N - Size[neighb]))
            continue;
        ++cnt;
        S[cnt].x = center;
        S[cnt].y = neighb;
        S[cnt].y2 = n;
    }
    return center;
}
int main()
{
    Read();
    centroidDecompose(1);
    printf("%d\n", cnt);
    for(int i = cnt; i >= 1; i--)
    {
        printf("%d %d %d\n", S[i].x, S[i].y, S[i].y2);
    }
    return 0;
}

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

using namespace std;
//using namespace __gnu_pbds;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
//typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;

#define FOR(i, a, b) for (int i=a; i<b; i++)
#define F0R(i, a) for (int i=0; i<a; i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)

#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
double PI = 4*atan(1);

int n, sub[200001], par[200001], centr[200001], cen = 1;
vi adj[200001];
vector<pair<int,pii>> ans;

void dfs(int node) {
    sub[node] = 1;
    for (int i: adj[node]) if (i != par[node]) {
        par[i] = node;
        dfs(i);
        sub[node] += sub[i];
    }
}

void dfs1(int node) {
    pii bes = {-1,-1};
    for (int i: adj[node]) if (i != par[node]) {
        dfs1(i);
        bes = max(bes,{sub[i],centr[i]});
    }
    centr[node] = node;
    if (bes.f*2 > sub[node] && n > sub[node]*2) {
        centr[node] = bes.s;
        ans.pb({par[node],{node,centr[node]}});
    }
}

int main() {
    cin >> n;
    F0R(i,n-1) {
        int a,b; cin >> a >> b;
        adj[a].pb(b), adj[b].pb(a);
    }

    dfs(1);
    while (1) {
        bool f = 0;
        for (int i: adj[cen]) if (i != par[cen] && 2*sub[i] > n) {
            cen = i;
            f = 1;
            break;
        }
        if (!f) break;
    }

    par[cen] = 0;
    dfs(cen);
    dfs1(cen);

    cout << ans.size() << "\n";
    for (auto a: ans) cout << a.f << " " << a.s.f << " " << a.s.s << "\n";
}

// read!
// ll vs. int!

#include<cstdio>
const int N=200005;
struct edge{
	int to,next;
}e[N<<1];
int h[N],n,xb,a,b,i,j,rt,rt2,sz[N],f[N],dfn[N],x[N],y[N],z[N],k,dad[N],lst;
inline void addedge(int a,int b){
	e[++xb]=(edge){b,h[a]};
	h[a]=xb;
	e[++xb]=(edge){a,h[b]};
	h[b]=xb;
}
inline void up(int&a,int b){
	if(a<b)a=b;
}
void dfs(int x,int fa){
	sz[x]=f[x]=1;
	for(int i=h[x];i;i=e[i].next)if(e[i].to!=fa)dfs(e[i].to,x),sz[x]+=sz[e[i].to],up(f[x],sz[e[i].to]);
	up(f[x],n-sz[x]);
	if(f[x]<b)rt=x,rt2=0,b=f[x];
		else if(f[x]==b)rt2=x;
}
void getv(int x,int fa){
	if(fa!=e[i].to && x!=e[i].to)dfn[++xb]=x,dad[xb]=fa;
	for(int j=h[x];j;j=e[j].next)if(e[j].to!=fa)getv(e[j].to,x);
}
int main(){
	scanf("%d",&n);
	for(i=1;i<n;++i){
		scanf("%d%d",&a,&b);
		addedge(a,b);
	}
	b=1<<30;
	dfs(1,0);
	for(i=h[rt];i;i=e[i].next)
		if(e[i].to!=rt2){
			xb=0;
			getv(lst=e[i].to,rt);
			for(j=1;j<=xb;++j){
				x[++k]=rt,y[k]=lst,z[k]=dfn[j];
				x[++k]=dfn[j],y[k]=dad[j],z[k]=e[i].to;
				lst=dfn[j];
			}
			x[++k]=rt,y[k]=lst,z[k]=e[i].to;
		}
	for(i=h[rt2];i;i=e[i].next)
		if(e[i].to!=rt){
			xb=0;
			getv(lst=e[i].to,rt);
			for(j=1;j<=xb;++j){
				x[++k]=rt2,y[k]=lst,z[k]=dfn[j];
				x[++k]=dfn[j],y[k]=dad[j],z[k]=e[i].to;
				lst=dfn[j];
			}
			x[++k]=rt2,y[k]=lst,z[k]=e[i].to;
		}
	printf("%d\n",k);
	for(i=1;i<=k;++i)printf("%d %d %d\n",x[i],y[i],z[i]);
	return 0;
}

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
#define ll long long
#define N 200010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,p[N],size[N],ansx[N],ansy[N],ansz[N],fa[N],top[N],pre[N],u,root,root2,t;
bool flag[N];
set<int> e[N];
struct data{int to,nxt;
}edge[N<<1];
void addedge(int x,int y){t++;e[x].insert(y);edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void make(int k,int from)
{
    size[k]=1;
    for (int i=p[k];i;i=edge[i].nxt)
    if (edge[i].to!=from)
    {
        make(edge[i].to,k);
        size[k]+=size[edge[i].to];
    }
}
int findroot(int k,int s,int from)
{
    int mx=0;
    for (int i=p[k];i;i=edge[i].nxt)
    if (edge[i].to!=from&&size[edge[i].to]>size[mx]) mx=edge[i].to;
    if ((size[mx]<<1)>s) return findroot(mx,s,k);
    else return k;
}
void solve(int k,int from)
{
	fa[k]=from;
	for (int i=p[k];i;i=edge[i].nxt)
	if (edge[i].to!=from&&edge[i].to!=root&&edge[i].to!=root2) solve(edge[i].to,k);
	for (int i=p[k];i;i=edge[i].nxt)
	if (edge[i].to!=from&&edge[i].to!=root&&edge[i].to!=root2)
	{
		if (!top[k]) top[k]=edge[i].to;
		ansx[++u]=fa[k];
		ansy[u]=k;
		ansz[u]=edge[i].to;
		e[ansx[u]].erase(ansy[u]),e[ansx[u]].insert(ansz[u]);
		e[ansy[u]].erase(ansx[u]),e[ansz[u]].insert(ansx[u]);
		fa[k]=top[edge[i].to];
	}
}//����kΪ�����������һ����
int get(int x)
{
	while (1)
	{
		auto it=e[x].begin();
		while (it!=e[x].end()&&(*it)==pre[x]) it++;
		if (it==e[x].end()) return x;
		else pre[*it]=x,x=*it;
	}
	return pre[x];
}
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	n=read();
	for (int i=1;i<n;i++)
	{
		int x=read(),y=read();
		addedge(x,y),addedge(y,x);
	}
	make(1,1);
	root=findroot(1,n,1);
	if (n%2==0)
	{
		for (int i=1;i<=n;i++)
		if (size[i]==n/2) {root2=i;break;}
	}
	if (root2)
	{
		for (int i=p[root2];i;i=edge[i].nxt)
		if (edge[i].to!=root)
		{
			solve(edge[i].to,root2);
			pre[top[edge[i].to]]=root2;
			int x=get(top[edge[i].to]),k=x;
			while (k!=root2)
			{
				ansx[++u]=pre[k];
				ansy[u]=k;
				ansz[u]=x;
				k=pre[k];
			}
		}
	}
	for (int i=p[root];i;i=edge[i].nxt)
	if (edge[i].to!=root2)
	{
		solve(edge[i].to,root);
		pre[top[edge[i].to]]=root;
		int x=get(top[edge[i].to]),k=x;
		while (k!=root)
		{
			ansx[++u]=pre[k];
			ansy[u]=k;
			ansz[u]=x;
			k=pre[k];
		}
	}
	printf("%d\n",u);
	for (int i=1;i<=u;i++)  printf("%d %d %d\n",ansx[i],ansy[i],ansz[i]);
	return 0;
	//NOTICE LONG LONG!!!!!
}

#pragma comment(linker, "/STACK:204800000,204800000")
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
#include <functional>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <sstream>
#include <unordered_set>
#include <unordered_map>
#include <sstream>
#include <set>
#include <cassert>
using namespace std;

//ifstream in("C:\\input.txt");
istream& in = cin;
struct Node{
	int x, y1, y2;
	Node(int a, int b, int c){
		x = a;
		y1 = b;
		y2 = c;
	}
};

#define pii pair<int,int>
#define mp make_pair
#define pb push_back
typedef long long LL;
#define MMAX ((int)2e5+10)
vector<Node> ans;
vector<int> edge[MMAX];
int dfs(int p,int f){
	if (edge[p].size() == 1 && edge[p].back() == f){
		return p;
	}

	if (p == 9){
		int t = 0;
	}

	int ret;
	for (int son : edge[p]){
		if (son == f)
			continue;
		ret = dfs(son, p);
		ans.push_back(Node(p, son, ret));
	}
	return ret;
}

int n;
vector<int> vi[MMAX];
bool mark[MMAX];

int pre_dfs(int p, int f, bool root){
	if (vi[p].size() == 1 && vi[p].back() == f){
		return p;
	}
	vector<pii> leaf;
	for (int son : vi[p]){
		if (son == f)
			continue;
		leaf.pb(mp(pre_dfs(son, p, 0),son));
	}

	if (root){
		if (p == 3){
			int t = 0;
		}
		for (int i = 0; i < leaf.size(); ++i){
			edge[leaf[i].first].push_back(p);
			edge[p].push_back(leaf[i].first);
			if (!mark[p])
				ans.push_back(Node(p, leaf[i].second, leaf[i].first));
		}
		return -1;
	}
	else{

		if (p ==11){
			int t = 0;
		}

		if (leaf.size() == 1){
			if (p == 2){
				int t = 0;
			}
			if (!mark[p])
				ans.push_back(Node(p, leaf[0].second, leaf[0].first));
			edge[p].push_back(leaf[0].first);
			edge[leaf[0].first].push_back(p);
			return leaf[0].second;
		}
		else{
			if (p == 7){
				int t = 0;
			}
			mark[f] = 1;
			ans.push_back(Node(f, p, leaf.back().first));
			int nowf = leaf.back().second;
			int nowp = p;
			for (int i = leaf.size() - 2; i >= 0; --i){
				ans.push_back(Node(nowf, nowp, leaf[i].first));

				edge[leaf[i].first].push_back(nowf);
				edge[nowf].push_back(leaf[i].first);
				nowf = leaf[i].second;
				nowp = p;

			}
			edge[p].push_back(nowf);
			edge[nowf].push_back(p);
		}
		return leaf.back().first;
	}
}

void input(){
	in >> n;
	for (int i = 1; i < n; ++i){
		int a, b;
		in >> a >> b;
		vi[a].pb(b);
		vi[b].pb(a);
	}
}
bool ok[MMAX];
int roota, rootb;
int get_root(int p,int f){
	int size = 1;
	for (int son : vi[p]){
		if (son == f)
			continue;
		int tmp = get_root(son, p);
		if (tmp < n - tmp){
			ok[son] = 1;
		}

		if ( n - tmp < tmp){
			ok[p] = 1;
		}

		size += tmp;
	}

	return size;
}

int main(){

	int TEST_CASE = 1;
	//in >> TEST_CASE;
	while (TEST_CASE-- > 0){
		input();
		if (n <= 3){
			cout << 0 << endl;
			continue;
		}
		roota = rootb = -1;

		get_root(1, -1);
		vector<int> vp;
		for (int i = 1; i <= n;++i)
		if (!ok[i])
			vp.push_back(i);

		assert(vp.size() <= 2);

		roota = vp[0];
		if (vp.size() == 2){
			rootb = vp.back();
		}

		pre_dfs(roota, rootb, 1);
		if (rootb != -1){
			pre_dfs(rootb, roota, 1);
		}

		dfs(roota, -1);
		if (rootb != -1){
			dfs(rootb, -1);
		}

		printf("%d\n", ans.size());
		for (Node& p : ans){
			printf("%d %d %d\n", p.x, p.y1, p.y2);
		}

	}

	return 0;
}

#include <bits/stdc++.h>
using namespace std;
const int maxn=2*100000+5;
#define MP make_pair
vector<int > g[maxn];
void addedge(int from,int to)
{
	g[from].push_back(to);
	g[to].push_back(from);
}
int n;
int siz[maxn],pa[maxn];
vector<pair<int ,pair<int ,int > > > Rlt;
void predfs(int v,int fa)
{
	siz[v]=1;
	for(int i=0;i<(int)g[v].size();i++){
		int u=g[v][i];
		if(u!=fa) {predfs(u,v);siz[v]+=siz[u];}
	}
}
pair<int ,int > FindCent(int v,int fa,int N)
{
	pa[v]=fa;
	pair<int ,int > Res=MP(0x3f3f3f3f,-1);
	int S=1;
	int maxsiz=0;
	for(int i=0;i<(int)g[v].size();i++){
		int u=g[v][i];
		if(u!=fa){
			Res=min(Res,FindCent(u,v,N));
			S+=siz[u];
			maxsiz=max(maxsiz,siz[u]);
		}
	}
	maxsiz=max(maxsiz,N-S);
	Res=min(Res,MP(maxsiz,v));
	return Res;
}
vector<pair<int ,int > > topo;
void dfs(int v,int fa)
{
	for(int i=0;i<(int)g[v].size();i++){
		int u=g[v][i];
		if(u!=fa) dfs(u,v);
	}
	topo.push_back(MP(v,fa));
}
void Getrlt(int v,int fa)
{
	topo.clear();
	dfs(v,fa);
	topo.pop_back();
	int iter=v;
	for(int i=0;i<(int)topo.size();i++){
		//if(iter!=topo[i].first)
			Rlt.push_back(MP(fa,MP(iter,topo[i].first)));
		//if(topo[i].second!=v)
			Rlt.push_back(MP(topo[i].first,MP(topo[i].second,v)));
		iter=topo[i].first;
	}
	Rlt.push_back(MP(fa,MP(iter,v)));
}
int main()
{
	//freopen("2.in","r",stdin);
	scanf("%d",&n);
	for(int i=0;i<n-1;i++){
		int from,to;
		scanf("%d%d",&from,&to);
		g[from].push_back(to);
		g[to].push_back(from);
	}
	predfs(1,-1);
	pair<int ,int > cent=FindCent(1,-1,n),cent2=MP(0,0);
	//printf("Cent: siz=%d v=%d\n",cent.first,cent.second);
	for(int i=1;i<=n;i++){
		if(i!=cent.second && siz[i]*2==n) cent2=MP(siz[i],i);
	}
	//for(int i=1;i<=n;i++){printf("siz[%d]=%d\n",i,siz[i]);}puts("");
	//printf("Cent2: siz=%d v=%d\n",cent2.first,cent2.second);
	for(int i=0;i<(int)g[cent.second].size();i++){
		int u=g[cent.second][i];
		if(u!=cent2.second) Getrlt(u,cent.second);
	}
	if(cent2!=MP(0,0))
		for(int i=0;i<(int)g[cent2.second].size();i++){
			int u=g[cent2.second][i];
			if(u!=cent.second) Getrlt(u,cent2.second);
		}
	printf("%d\n",Rlt.size());
	for(int i=0;i<(int)Rlt.size();i++){
		printf("%d %d %d\n",Rlt[i].first,Rlt[i].second.first,Rlt[i].second.second);
	}
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef double D;
typedef long long int LL;

#define st first
#define nd second
#define pb push_back
#define PLL pair <LL, LL>
#define PII pair <int, int>
#define PIII pair <PII, int>

const int N = 2e5 + 7;
const int MX = 1e9 + 7;
const int inf = 1e9 + 9;

int n, m;
int pod[N];
bool block[N];
vector <int> G[N];
vector <PIII> res;

int dfs(int u, int p){
	pod[u] = 1;
	for(int v: G[u])
		if(v != p && !block[v])
			pod[u] += dfs(v, u);
	return pod[u];
}

int centroid(int u){
	dfs(u, u);
	int par = u;
	int half = (pod[u] + 1) / 2;

	bool change = true;
	while(change){
		change = false;
		for(int v: G[u])
			if(pod[v] >= half && !block[v] && v != par){
				change = true;
				par = u;
				u = v;
				break;
			}
	}

	return u;
}

int Rozbicie(int u){
	u = centroid(u);
	block[u] = true;
	for(int v: G[u]){
		if(block[v])	continue;
		res.pb({{u, v}, Rozbicie(v)});
	}

	return u;
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i < n; ++i){
		int u, v;
		scanf("%d %d", &u, &v);
		G[u].pb(v);
		G[v].pb(u);
	}

	Rozbicie(1);
	printf("%d\n", (int)res.size());
	for(int i = res.size() - 1; i >= 0; --i)
		printf("%d %d %d\n", res[i].st.st, res[i].st.nd, res[i].nd);
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

#define MAXN 200010
#define INF 0x3f3f3f3f
typedef long long LL;

int n;
int Size[MAXN], mSize[MAXN];
int root, mmsize, mmroot;
bool vis[MAXN];
vector< int > adj[MAXN];

vector< pair<int, pair<int, int> > > ans;

void DFS_Size(int u, int fa)
{
    Size[u] = 1; mSize[u] = 0;
    for(auto &v: adj[u]){
        if(vis[v] || v == fa) continue;
        DFS_Size(v, u);
        Size[u] += Size[v];
        mSize[u] = max(mSize[u], Size[v]);
    }
}

void DFS_Centre(int u, int fa)
{
    mSize[u] = max(mSize[u], Size[root] - Size[u]);
    if(mSize[u] < mmsize){
        mmsize = mSize[u];
        mmroot = u;
    }
    for(auto &v: adj[u]){
        if(vis[v] || v == fa) continue;
        DFS_Centre(v, u);
    }
}

void DFS(int u, int fa)
{
    root = u;
    mmsize = n;
    DFS_Size(u, 0);
    if(Size[u] != n && Size[u] >= n - Size[u]) mmroot = u;
    else DFS_Centre(u, 0);
    vis[mmroot] = true;
    if(fa && mmroot != u) ans.push_back({fa, {u, mmroot}});
    u = mmroot;
    for(auto &v: adj[u]){
        if(vis[v]) continue;
        DFS(v, u);
    }
}

void Init()
{
    int i, u, v;
    scanf("%d", &n);
    for(i = 1; i < n; ++i){
        scanf("%d %d", &u, &v);
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
}

void Work()
{
    DFS(1, 0);
    printf("%d\n", ans.size());
    for(auto &it: ans){
        printf("%d %d %d\n", it.first, it.second.first, it.second.second);
    }
}

int main()
{
    Init();
    Work();
    return 0;
}

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

typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<VI> VVI;
const int INF = 2000000000;

VVI adj;
PII dfsBamboo(int u, const function<void(int,int,int)> &emit, int p = -1){
	vector<PII> leaves;
	for(int v : adj[u]){
		if(v == p)continue;
		leaves.push_back( dfsBamboo(v, emit, u) );
	}
	if(leaves.size() == 0)return PII(u, u);
	for (int i = 0; i < leaves.size(); ++i) {
		if(i == 0){
			emit(p, u, leaves[i].second);
		}else{
			emit(leaves[i-1].first, u, leaves[i].second);
		}
	}
	return PII(leaves[0].second, u);
}
int dfsStar(int u, const function<void(int,int,int)> &emit, int p = -1) {
	for(int v : adj[u]){
		if(v == p)continue;
		int nch = dfsStar(v, emit, u);
		emit(p, u, nch);
		return nch;
	}
	return u;

}
PII cp(int a, int b){
	return PII(min(a,b), max(a,b));
}
int SZ[200010];
int dfsSize(int u,int p = -1){
	SZ[u] = 1;
	for(int v : adj[u])
		if(v != p)
			SZ[u] += dfsSize(v, u);
	return SZ[u];
}

struct Change {
	int u,v0,v1;
};
int main()
{
	int N;
	cin >> N;
	adj = VVI(N);
	set<PII> S;
	for (int i = 0; i < N-1; ++i) {
		int u,v;
		cin >> u >> v;
		u--;v--;
		S.insert(cp(u,v));
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	dfsSize(0);
	vector<int> CD;

	for (int u = 0; u < N; ++u) {
		int b = 0;
		for(int v : adj[u]){
			int csz = SZ[v] < SZ[u] ? SZ[v] : (N-SZ[v]);
			b = max(b, csz);
		}
		if(b*2 <= N)
			CD.push_back(u);
	}
	vector<Change> CH;
	for(int c : CD){
		for(int v : adj[c]){
			if(find(CD.begin(), CD.end(), v) != CD.end())continue;
			dfsBamboo(v, [&S, &CH](int u, int v0, int v1) {
				S.erase(cp(u,v0));
				S.insert(cp(u,v1));
				CH.push_back({u+1, v0+1, v1+1});
			}, c);
		}
	}
	adj = VVI(N);
	for(PII p : S){
		adj[p.first].push_back(p.second);
		adj[p.second].push_back(p.first);
	}
	for(int c : CD){
		for(int v : adj[c]){
			if(find(CD.begin(), CD.end(), v) != CD.end())continue;
			dfsStar(v, [&S, &CH](int u, int v0, int v1) {
				S.erase(cp(u,v0));
				S.insert(cp(u,v1));
				CH.push_back({u+1, v0+1, v1+1});
			}, c);
		}
	}
	cout << CH.size() << endl;
	for(Change &c : CH)
		cout << c.u << " " << c.v0 << " " << c.v1 << endl;
}

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
using namespace __gnu_pbds;
using namespace std;

const int MAXN = 200000 + 20, MAXM = 20, MOD = 1000 * 1000 * 1000 + 7;
const long long INF = 1e9 + 10;
int d[MAXN], vis[MAXN], cen[MAXN];
vector <int> vec[MAXN];
int n, centr, lasti;
vector <pair <int, pair <int, int> > > ans;

void centroid(int u) {
	vis[u] = 1;
	bool cent = 1;
	int t = 1;
	for (int i = 0; i < vec[u].size(); i++) {
		int v = vec[u][i];
		if (!vis[v]) {
			centroid(v);
			t += d[v];
			if (d[v] > n / 2)
				cent = 0;
		}
	}

	d[u] = t;
	if (n  - d[u] > n / 2)
		cent = 0;
	if (cent) {
		cen[u] = 1;
		centr = u;
	}
}

void change(int u, int par, int j, int cn) {
	if (cen[u] == 1) {
		for (int i = 0; i < vec[u].size(); i++) {
			int v = vec[u][i];
			if (v != par) {
				lasti = v;
				change (v, u, v, u);
			}
		}
	}
	else {
		for (int i = 0; i < vec[u].size(); i++) {
			int v = vec[u][i];
			if (v != par)
				change(v, u, j, cn);
		}

		if (u != j) {
			ans.push_back(make_pair(cn, make_pair(lasti, u)));
			lasti = u;
			ans.push_back(make_pair(u, make_pair(par, j)));
		}
		else
			ans.push_back(make_pair(u, make_pair(lasti, j)));
	}
}
void solve() {
	cin >> n;
	for (int i = 0, u, v; i < n - 1; i++){
		cin >> u >> v;
		vec[u].push_back(v);
		vec[v].push_back(u);
	}

	centroid(1);
	change(centr, 0, 0, 0);
	cout << ans.size() << endl;
	for (int i = 0; i < ans.size(); i++)
		cout << ans[i].first << " " << ans[i].second.first << " " << ans[i].second.second << endl;
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	solve();
}

#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
int N, M;
vector <int> G[200005];
int Next[200005];
int Array[200005];
int Sz[200005], Size[200005];
int sum, cnt;
bool Blocked[200005];
struct Solution{
int x, y, y2;
} S[400005];
bool first;
int End[200005], Start[200005];
void Read()
{
    scanf("%d", &N);
    for(int i = 2; i <= N; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
}

void DFS(int node, int father)
{
    Sz[node] = 1;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        DFS(neighb, node);
        Sz[node] += Sz[neighb];
    }
}

int findCentroid(int node, int father, int size)
{
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        if(Sz[neighb] > size / 2)
            return findCentroid(neighb, node, size);
    }
    return node;
}

void makeBamboo(int node, int father)
{
    int f = father;
    int ct = 0;
    int last = node;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father)
            continue;
        if(ct == 0)
            Start[node] = End[neighb];
        makeBamboo(neighb, node);
        last = End[neighb];
        ct++;
    }
    if(ct == 0)
        End[node] = Start[node] = node;
    else
    {
        End[node] = last;
        for(int i = 0; i < G[node].size(); i++)
        {
            int neighb = G[node][i];
            if(neighb == father)
                continue;
            ++cnt;
            S[cnt].x = f;
            S[cnt].y = node;
            S[cnt].y2 = End[neighb];
            Next[f] = End[neighb];
            f = Start[neighb];
        }
    }
}

void makeStar(int node)
{
    int ct = 0;
    int ind = 0;
    while(node != 0)
    {
        ++ct;
        Array[++ind] = node;
        node = Next[node];
    }
    for(int i = ind - 2; i >= 1; i--)
    {
        ++cnt;
        S[cnt].x = Array[i];
        S[cnt].y = Array[i + 1];
        S[cnt].y2 = Array[ind];
    }
}
int main()
{
    Read();
    int root = 1;
    DFS(root, 0);
    bool ok = 0;
    int center = findCentroid(root, 0, Sz[root]);
    for(int i = 0; i < G[center].size(); i++)
    {
        int neighb = G[center][i];
        if(Sz[neighb] == N - Sz[neighb])
        {
            /*for(auto it = G[neighb].begin(); it != G[neighb].end(); it = next(it))
                if(*it == center)
                {
                    G[neighb].erase(it);
                    break;
                }

            swap(G[center][i], G[center][G[center].size() - 1]);
            G[center].pop_back();*/
            ok = 1;
            Blocked[center] = 1;
            Blocked[neighb] = 1;
            int node = center;
            for(int i = 0; i < G[node].size(); i++)
            {
                int neighb = G[node][i];
                int from = center;
                if(Blocked[neighb] == 1)
                    continue;

                makeBamboo(neighb, node);
                makeStar(node);
            }
            node = neighb;
            for(int i = 0; i < G[node].size(); i++)
            {
                int neighb = G[node][i];
                int from = center;
                if(Blocked[neighb] == 1)
                    continue;

                makeBamboo(neighb, node);
                makeStar(node);
            }
            break;
        }
    }
    if(ok == 0)
    {
        int node = center;
            for(int i = 0; i < G[node].size(); i++)
            {
                int neighb = G[node][i];
                int from = center;
                if(Blocked[neighb] == 1)
                    continue;

                makeBamboo(neighb, node);
                makeStar(node);
            }
    }
//8
    printf("%d\n", cnt);
    for(int i = 1; i <= cnt; i++)
    {
        printf("%d %d %d\n", S[i].x, S[i].y, S[i].y2);
    }
    return 0;
}

#pragma region Macros
#pragma GCC optimize("O3")

#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i,a,b) for(ll i=a;i<=b;++i)
#define rep(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i>=b;--i)
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vec vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1,_2,name,...) name
#define vv(a,b) vector<vector<int>>(a,vector<int>(b))
#define vv2(a,b,c) vector<vector<int>>(a,vector<int>(b,c))
#define vvl(a,b) vector<vector<ll>>(a,vector<ll>(b))
#define vvl2(a,b,c) vector<vector<ll>>(a,vector<ll>(b,c))
#define vvv(a,b,c) vector<vv(b,c)>(a)
#define vvv2(a,b,c,d) vector<vv(b,c,d)>(a)
#define vvvl(a,b,c) vector<vvl(b,c)>(a)
#define vvvl2(a,b,c,d) vector<vvl(b,c,d)>(a)
#define fi first
#define se second
#define all(c) begin(c),end(c)
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define lb(c,x) distance((c).begin(),lower_bound(all(c),(x)))
#define ub(c,x) distance((c).begin(),upper_bound(all(c),(x)))
using namespace std;
template<class T> using pq = priority_queue<T>;
template<class T> using pqg = priority_queue<T,vector<T>,greater<T>>;
#define INT(...) int __VA_ARGS__;IN(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;IN(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__;IN(__VA_ARGS__)
#define STR(...) string __VA_ARGS__;IN(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__;IN(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__;IN(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__;IN(__VA_ARGS__)
#define VEC(type,name,size) vector<type> name(size);IN(name)
#define VV(type,name,h,w) vector<vector<type>>name(h,vector<type>(w));IN(name)
int scan(){ return getchar(); }
void scan(int& a){ cin>>a; }
void scan(long long& a){ cin>>a; }
void scan(char &a){cin>>a;}
void scan(double &a){ cin>>a; }
void scan(long double& a){ cin>>a; }
void scan(char a[]){ scanf("%s", a); }
void scan(string& a){ cin >> a; }
template<class T> void scan(vector<T>&);
template<class T, size_t size> void scan(array<T, size>&);
template<class T, class L> void scan(pair<T, L>&);
template<class T, size_t size> void scan(T(&)[size]);
template<class T> void scan(vector<T>& a){ for(auto& i : a) scan(i); }
template<class T> void scan(deque<T>& a){ for(auto& i : a) scan(i); }
template<class T, size_t size> void scan(array<T, size>& a){ for(auto& i : a) scan(i); }
template<class T, class L> void scan(pair<T, L>& p){ scan(p.first); scan(p.second); }
template<class T, size_t size> void scan(T (&a)[size]){ for(auto& i : a) scan(i); }
template<class T> void scan(T& a){ cin >> a; }
void IN(){}
template <class Head, class... Tail> void IN(Head& head, Tail&... tail){ scan(head); IN(tail...); }
string stin() {string s;cin>>s;return s;}
template<class T> inline bool chmax(T& a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T> inline bool chmin(T& a,T b){if(a>b){a=b;return 1;}return 0;}
vi iota(int n){vi a(n);iota(all(a),0);return a;}
template<class T> void UNIQUE(vector<T> &x){sort(all(x));x.erase(unique(all(x)),x.end());}
int in() {int x;cin>>x;return x;}
ll lin() {unsigned long long x;cin>>x;return x;}
void print(){putchar(' ');}
void print(bool a){cout<<a;}
void print(int a){cout<<a;}
void print(long long a){cout<<a;}
void print(char a){cout<<a;}
void print(string &a){cout<<a;}
void print(double a){cout<<a;}
template<class T> void print(const vector<T>&);
template<class T, size_t size> void print(const array<T, size>&);
template<class T, class L> void print(const pair<T, L>& p);
template<class T, size_t size> void print(const T (&)[size]);
template<class T> void print(const vector<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } cout<<endl;}
template<class T> void print(const deque<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } }
template<class T, size_t size> void print(const array<T, size>& a){ print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } }
template<class T, class L> void print(const pair<T, L>& p){ cout<<'(';print(p.first); cout<<","; print(p.second);cout<<')'; }
template<class T, size_t size> void print(const T (&a)[size]){ print(a[0]); for(auto i = a; ++i != end(a); ){ cout<<" "; print(*i); } }
template<class T> void print(const T& a){ cout << a; }
int out(){ putchar('\n'); return 0; }
template<class T> int out(const T& t){ print(t); putchar('\n'); return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; }
ll gcd(ll a, ll b){ while(b){ ll c = b; b = a % b; a = c; } return a; }
ll lcm(ll a, ll b){ if(!a || !b) return 0; return a * b / gcd(a, b); }
vector<pll> factor(ll x){ vector<pll> ans; for(ll i = 2; i * i <= x; i++) if(x % i == 0){ ans.push_back({i, 1}); while((x /= i) % i == 0) ans.back().second++; } if(x != 1) ans.push_back({x, 1}); return ans; }
vector<int> divisor(int x){ vector<int> ans; for(int i=1;i*i<=x;i++)if(x%i==0){ans.pb(i);if(i*i!=x)ans.pb(x/i);} return ans;}
int popcount(ll x){return __builtin_popcountll(x);}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int n){return uniform_int_distribution<int>(0, n)(rng);}
#define endl '\n'

#ifdef _LOCAL
    #undef endl
    #define debug(x) cout<<#x<<": ";print(x);cout<<endl;
    void err(){}
    template<class T> void err(const T& t){ print(t);  cout<<" ";}
    template<class Head, class... Tail> void err(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); }
#else
    #define debug(x)
    template<class... T> void err(const T&...){}
#endif
#pragma endregion

template< typename T >
struct edge{
    int from, to;
    T cost;
    edge(int to,T cost) : from(-1), to(to), cost(cost){}
    edge(int from,int to,T cost) : from(from), to(to), cost(cost){}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const{ return to;}
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedTree = vector< Edges<T>>;
using tree = vector< vector<int> >;
using UnWeightedGraph = tree;
tree make(int n,int offset = 1){
    tree res(n);
    for(int i = 0;i < n-1; i++){
        int a,b; cin >> a >> b;
        a -= offset,b -= offset;
        res[a].emplace_back(b);
        res[b].emplace_back(a);
    }
    return res;
}
template< typename T >
WeightedTree<T> make2(int n, int offset = 1){
    WeightedTree<T> res(n);
    for(int i = 0;i < n-1 ; i++){
        int a,b ; cin >> a >> b;
        a -= offset, b -= offset;
        T c; cin >> c;
        res[a].emplace_back(b,c);
        res[b].emplace_back(a,c);
    }
    return res;
}

tuple<int,int,int> buff;
vector<tuple<int,int,int>> ans;
template< typename G >
struct CentroidDecomposition {
  G g;
  vector< int > sub;
  vector< ll > d; // 距離の和
  vector< ll > dp; // 二乗和を rerootingで
  vector< vector< int > > belong;
  vector< bool > v;
  vector< int > p;

  CentroidDecomposition(const G g) : g(g), sub(g.size()), v(g.size()), belong(g.size()), p(g.size()), d(g.size()), dp(g.size()) {}

  inline int build_dfs(int idx, int par) {
    p[idx] = par;
    sub[idx] = 1;
    d[idx] = dp[idx] = 0;
    for(auto &to : g[idx]) {
      if(to == par || v[to]) continue;
      sub[idx] += build_dfs(to, idx);
      d[idx] += d[to] + sub[to];
      dp[idx] += dp[to] + d[to] * 2 + sub[to];
    }
    return sub[idx];
  }

  inline void rerooting(int idx,int par,ll &mi,int &centroid){
      if(par != -1){
        dp[idx] += (dp[par] - dp[idx] - d[idx]*2 - sub[idx]) + (d[par] - (d[idx] + sub[idx]) ) * 2 + (sub[par] - sub[idx]);
        d[idx] += (d[par] - (d[idx] + sub[idx])) + (sub[par] - sub[idx]);
        sub[idx] += sub[par] - sub[idx];
      }
      if(chmin(mi,dp[idx])) centroid = idx;
      for(auto &to : g[idx]){
          if(to == par || v[to]) continue;
          rerooting(to,idx,mi,centroid);
      }
  }

  inline int search_centroid(int idx, int par, const int mid) {
    for(auto &to : g[idx]) {
      if(to == par || v[to]) continue;
      if(sub[to] > mid) return search_centroid(to, idx, mid);
    }
    return idx;
  }

  inline void belong_dfs(int idx, int par, int centroid) {
    belong[idx].emplace_back(centroid);
    for(auto &to : g[idx]) {
      if(to == par || v[to]) continue;
      belong_dfs(to, idx, centroid);
    }
  }

  inline int build(UnWeightedGraph &t, int idx,bool start = false) {
    if(start){
        int centroid = search_centroid(idx, -1, build_dfs(idx, -1) / 2);
        v[centroid] = true;
        build_dfs(centroid,-1);
        bool flag = false;
        int c2;
        for(auto e:g[centroid]) if(~g.size()&1 and sub[e] == g.size()/2) flag = true,c2 = e;
        if(!flag){
            for(auto &to : g[centroid]) {
                if(!v[to]) {
                    int st = ans.size();
                    ans.eb(buff);
                    t[centroid].emplace_back(build(t, to));
                    ans[st] = {centroid,to,t[centroid].back()};
                    g[to].erase(find(all(g[to]),centroid));
                    to = t[centroid].back();
                    g[t[centroid].back()].eb(centroid);
                }
            }
        }
        else{
            v[c2] = true;
            for(auto &to:g[centroid]){
                if(!v[to]){
                    int st = ans.size();
                    ans.eb(buff);
                    t[centroid].eb(build(t,to));
                    ans[st] = {centroid,to,t[centroid].back()};
                    g[to].erase(find(all(g[to]),centroid));
                    to = t[centroid].back();
                    g[t[centroid].back()].eb(centroid);
                }
            }
            for(auto &to:g[c2]){
                if(!v[to]){
                    int st = ans.size();
                    ans.eb(buff);
                    t[c2].eb(build(t,to));
                    ans[st] = {c2,to,t[c2].back()};
                    g[to].erase(find(all(g[to]),c2));
                    to = t[c2].back();
                    g[t[c2].back()].eb(c2);
                }
            }
            v[c2] = false;
        }
        v[centroid] = false;
        return centroid;
    }
    else{
        build_dfs(idx,-1);
        int centroid;
        ll mi = LONG_LONG_MAX;
        rerooting(idx,-1,mi,centroid);
        v[centroid] = true;
        for(auto &to:g[centroid]){
            if(!v[to]){
                int st = ans.size();
                ans.eb(buff);
                t[centroid].emplace_back(build(t,to));
                ans[st] = {centroid,to,t[centroid].back()};
                g[to].erase(find(all(g[to]),centroid));
                to = t[centroid].back();
                g[t[centroid].back()].eb(centroid);
            }
        }
        v[centroid] = false;
        return centroid;
    }

  }

  inline int build(UnWeightedGraph &t,bool start = false) {
    t.resize(g.size());
    return build(t, 0,start);
  }
};

signed main(){
    // ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);cout<<fixed<<setprecision(15);
    INT(n);
    tree g = make(n);
    for(auto e:g)sort(all(e));
    CentroidDecomposition CD(g);
    tree t;
    CD.build(t,true);
    cout << ans.size()<<endl;
    for(auto [a,b,c]:ans){
        cout<<++a<<" "<<++b<<" "<<++c<<endl;
    }
}

#include<iostream>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<cctype>
#include<cassert>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<cstring>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<iomanip>
#include<utility>
using namespace std;
#define mp make_pair
#define pb push_back
#define X first
#define Y second
#define rg register
#define il inline
#define lch(x) ((x)<<1)
#define rch(x) ((x)<<1^1)
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
#define rep0(i,n) for(register int i=0;i<(n);++i)
#define per0(i,n) for(register int i=(n)-1;i>=0;--i)
#define rep(i,st,ed) for(register int i=(st);i<=(ed);++i)
#define per(i,ed,st) for(register int i=(ed);i>=(st);--i)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef double dbl;
typedef long double ldb;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
template<typename T> il T qmin(const T &a,const T &b){return a<b?a:b;}
template<typename T> il T qmax(const T &a,const T &b){return a>b?a:b;}
template<typename T> il void getmin(T &a,const T &b){if(a>b) a=b;}
template<typename T> il void getmax(T &a,const T &b){if(a<b) a=b;}
il void fileio(string s){
	freopen((s+".in").c_str(),"r",stdin);
	freopen((s+".out").c_str(),"w",stdout);
}

const int inf=(int)1e9+7;
const ll linf=(ll)1e17+7;
const int N=2e5+7,M=N<<1;

int v[M],nxt[M];
int head[N],sz[N],n;
pii cur;
vector<pair<pii,int> > ans;

il void addedge(int p,int x,int y){
	v[p]=y,nxt[p]=head[x],head[x]=p;
}

il void getsz(int u,int p){
	sz[u]=1;
	for(int e=head[u];e;e=nxt[e]){
		if(v[e]==p) continue;
		getsz(v[e],u);
		sz[u]+=sz[v[e]];
	}
}

il pii getcen(int u,int p,int tot){
	for(int e=head[u];e;e=nxt[e]){
		if(v[e]==p) continue;
		if(sz[v[e]]*2>tot) return getcen(v[e],u,tot);
		if(sz[v[e]]*2==tot) return mp(u,v[e]);
	}
	return mp(u,u);
}

il void dfs(int u,int p,int des){
	for(int e=head[u];e;e=nxt[e]){
		if(v[e]==p) continue;
		if(u!=des){
			ans.pb(mp(cur,v[e]));
			cur.Y=v[e];
			ans.pb(mp(mp(v[e],u),des));
		}
		dfs(v[e],u,des);
	}
}

int main(){
	scanf("%d",&n);
	rep(i,1,n-1){
		int x,y;
		scanf("%d%d",&x,&y);
		addedge(lch(i),x,y);
		addedge(rch(i),y,x);
	}
	getsz(1,0);
	pii p=getcen(1,0,sz[1]);
	if(p.X==p.Y){
		int u=p.X;
		for(int e=head[u];e;e=nxt[e]){
			cur=mp(u,v[e]);
			dfs(v[e],u,v[e]);
			ans.pb(mp(cur,v[e]));
		}
	}else{
		int u=p.X;
		for(int e=head[u];e;e=nxt[e]){
			if(v[e]==p.Y) continue;
			cur=mp(u,v[e]);
			dfs(v[e],u,v[e]);
			ans.pb(mp(cur,v[e]));
		}
	}
	printf("%d\n",ans.size());
	rep0(i,ans.size()) printf("%d %d %d\n",ans[i].X.X,ans[i].X.Y,ans[i].Y);
	return 0;
}

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

struct Transformation {
	const int x, y, yp;
};

const int MAX_N = 2e5;

int n, sizeOfSubtree[MAX_N + 1], centroid, leaf[MAX_N + 1];
pair<int, int> centroids;
bool singleCentroid;
unordered_set<int> adjacencyList[MAX_N + 1];
vector<Transformation> transformations;

template<typename valueType, template<typename = valueType, typename... arguments> class containerType>
vector<valueType> copy(const containerType<valueType>& container) {
	vector<valueType> result;
	result.reserve(container.size());
	for (const valueType element : container)
		result.push_back(element);
	return result;
}

void removeEdge(const int vertex, const int adjacent) {
	// cout << "removing edge between " << vertex << " and " << adjacent << endl;
	/*
	cout << "vertex adjacents (before): " << endl;
	for (int a : adjacencyList[vertex])
		cout << a << endl;
	cout << "adjacent adjacents (before): " << endl;
	for (int a : adjacencyList[adjacent])
		cout << a << endl;
	*/
	adjacencyList[vertex].erase(adjacent);
	adjacencyList[adjacent].erase(vertex);
	// cout << "edge removed" << endl;
	return;
}

void addEdge(const int vertex, const int adjacent) {
	// cout << "adding edge between " << vertex << " and " << adjacent << endl;
	/*
	cout << "vertex adjacents (before): " << endl;
	for (int a : adjacencyList[vertex])
		cout << a << endl;
	cout << "adjacent adjacents (before): " << endl;
	for (int a : adjacencyList[adjacent])
		cout << a << endl;
	*/
	adjacencyList[vertex].insert(adjacent);
	adjacencyList[adjacent].insert(vertex);
	// cout << "edge added" << endl;
	return;
}

void transform(const int x, const int y, const int yp) {
	// cout << "trasnforming on " << x << ' ' << y << ' ' << yp << endl;
	removeEdge(x, y);
	addEdge(x, yp);
	transformations.push_back({x, y, yp});
	// cout << "done transforming on " << x << ' ' << y << ' ' << yp << endl;
	return;
}

void calculateSizeOfSubtrees(const int root, const int parent) {
	/*
	cout << "in calculate size of subtree" << endl;
	cout << "root: " << root << endl;
	cout << "parent: " << parent << endl;
	*/
	sizeOfSubtree[root] = 1;
	for (const int adjacent : copy(adjacencyList[root])) {
		if (adjacent != parent) {
			calculateSizeOfSubtrees(adjacent, root);
			sizeOfSubtree[root] += sizeOfSubtree[adjacent];
		}
	}
	/*
	cout << "size of subtree: " << sizeOfSubtree[root] << endl;
	cout << "root: " << root << endl;
	cout << "parent: " << parent << endl;
	*/
	return;
}

void calculateCentroid() {
	// cout << "in calculate centroid" << endl;
	int root = 1;
	bool foundCentroid = false;
	calculateSizeOfSubtrees(root, -1);
	while (not foundCentroid) {
		// cout << "root: " << root << endl;
		foundCentroid = true;
		for (const int adjacent : copy(adjacencyList[root])) {
			if (sizeOfSubtree[adjacent] * 2 > n) {
				// cout << "root cannot be centroid because of an adjacent" << endl;
				// cout << "root: " << root << endl;
				// cout << "adjacent: " << adjacent << endl;
				foundCentroid = false;
				sizeOfSubtree[root] = n - sizeOfSubtree[adjacent];
				sizeOfSubtree[adjacent] = n;
				root = adjacent;
				// cout << "updated sizes: " << endl;
				/*for (int v = 1; v <= n; ++v)
					cout << sizeOfSubtree[v] << ' ';
				cout << endl;*/
				break;
			} else if (sizeOfSubtree[adjacent] * 2 == n) {
				// cout << "root and its adjacent are centroids together" << endl;
				// cout << "root: " << root << endl;
				// cout << "adjacent: " << adjacent << endl;
				singleCentroid = false;
				centroids = {root, adjacent};
				return;
			}
		}
	}
	//cout << "finally, our signle centroid is: " << root << endl;
	singleCentroid = true;
	centroid = root;
	return;
}

void makeAdjacentBamboo(const int vertex, const int adjacent) {
	// cout << "in make adjacent bamboo" << endl;
	// cout << "vertex: " << vertex << endl;
	// cout << "adjacent: " << adjacent << endl;
	if (adjacencyList[adjacent].size() == 1) {
		// cout << "adjacent is leaf" << endl;
		// cout << "vertex: " << vertex << endl;
		// cout << "adjacent: " << adjacent << endl;
		leaf[adjacent] = adjacent;
		if (adjacencyList[vertex].size() <= 2) {
			// cout << "vertex is leaf/pre-root" << endl;
			leaf[vertex] = adjacent;
		}
	} else {
		// cout << "adjacnet is not a leaf" << endl;
		// cout << "vertex: " << vertex << endl;
		// cout << "adjacent: " << adjacent << endl;
		for (const int adjacentOfAdjacent : copy(adjacencyList[adjacent])) {
			// cout << "in the loop" << endl;
			// cout << "vertex: " << vertex << endl;
			//cout << "adjacent: " << adjacent << endl;
			//cout << "adjacent of adjacent: " << adjacentOfAdjacent << endl;
			if (adjacentOfAdjacent != vertex) {
				//cout << "calling make adjacent bamboo" << endl;
				makeAdjacentBamboo(adjacent, adjacentOfAdjacent);
			}
		}
		//cout << "after loop" << endl;
		//cout << "vertex: " << vertex << endl;
		//cout << "adjacnet: " << adjacent << endl;
		if (adjacencyList[adjacent].size() <= 2) {
			//cout << "adjacent is bamboo" << endl;
			if (adjacencyList[vertex].size() <= 2) {
				//cout << "vertex is leaf/pre-root" << endl;
				leaf[vertex] = leaf[adjacent];
			}
		} else {
			//cout << "adjacent is not bamboo" << endl;
			int adjacentOfAdjacent = *adjacencyList[adjacent].begin();
			if (adjacentOfAdjacent == vertex)
				adjacentOfAdjacent = *(++adjacencyList[adjacent].begin());
			//cout << "adjacent of adjacent: " << adjacentOfAdjacent << endl;
			transform(vertex, adjacent, leaf[adjacentOfAdjacent]);
			//cout << "calling make adjacent bamboo" << endl;
			makeAdjacentBamboo(adjacentOfAdjacent, adjacent);
			if (adjacencyList[vertex].size() <= 2) {
				//cout << "vertex is leaf/pre-root" << endl;
				//cout << "vertex: " << vertex << endl;
				//cout << "adjacnet: " << adjacent << endl;
				leaf[vertex] = leaf[adjacentOfAdjacent];
			}
		}
	}
	//cout << "done making adjacent bamboo" << endl;
	//cout << "vertex: " << vertex << endl;
	//cout << "adjacent: " << adjacent << endl;
	return;
}

void makeAdjacentHedgehog(const int vertex, const int adjacent) {
	//cout << "in make adjacent hedgehog" << endl;
	//cout << "vertex: " << vertex << endl;
	//cout << "adjacent: " << adjacent << endl;
	if (adjacencyList[adjacent].size() == 1) {
		//cout << "p2 does not need any operation" << endl;
		//cout << "done making hedgehog" << endl;
		return;
	}
	makeAdjacentBamboo(vertex, adjacent);
	const int hedgehogCenter = *adjacencyList[leaf[adjacent]].begin();
	//cout << "hedgehog's center: " << hedgehogCenter << endl;
	int lastSpine = *adjacencyList[hedgehogCenter].begin();
	if (lastSpine == leaf[adjacent])
		lastSpine = *(++adjacencyList[hedgehogCenter].begin());
	while (lastSpine != vertex) {
		//cout << "last spine: " << lastSpine << endl;
		int adjacentOfLastSpine = *adjacencyList[lastSpine].begin();
		if (adjacentOfLastSpine == hedgehogCenter)
			adjacentOfLastSpine = *(++adjacencyList[lastSpine].begin());
		//cout << "adjacent of last spine: " << adjacentOfLastSpine << endl;
		transform(adjacentOfLastSpine, lastSpine, hedgehogCenter);
		lastSpine = adjacentOfLastSpine;
	}
	//cout << "done making hedgehog" << endl;
	//cout << "vertex: " << vertex << endl;
	//cout << "adjacent: " << adjacent << endl;
	return;
}

void optimizeIO() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
}

int main() {
	optimizeIO();
	//cout << "in main" << endl;
	cin >> n;
	for (int i = 1, a, b; i <= n - 1; ++i) {
		cin >> a >> b;
		addEdge(a, b);
	}
	//cout << "read inputs" << endl;
	calculateCentroid();
	//cout << "calculated centroids" << endl;
	//cout << boolalpha << "single centroid: " << singleCentroid << endl;
	if (singleCentroid)
		for (const int adjacent : copy(adjacencyList[centroid]))
			makeAdjacentHedgehog(centroid, adjacent);
	else {
		for (const int adjacent : copy(adjacencyList[centroids.first]))
			if (adjacent != centroids.second)
				makeAdjacentHedgehog(centroids.first, adjacent);
		for (const int adjacent : copy(adjacencyList[centroids.second]))
			if (adjacent != centroids.first)
				makeAdjacentHedgehog(centroids.second, adjacent);
	}
	//cout << "printing output" << endl;
	if (singleCentroid) {
		for (const int centroidAdjacent : adjacencyList[centroid])
			for (const int adjacentToCentroidAdjacent : adjacencyList[centroidAdjacent])
				if (adjacentToCentroidAdjacent != centroid and adjacencyList[adjacentToCentroidAdjacent].size() != 1) {
					cout << adjacentToCentroidAdjacent << ' ' << adjacencyList[adjacentToCentroidAdjacent].size() << endl;
					for (int x : adjacencyList[adjacentToCentroidAdjacent])
						cout << x << ' ' << adjacencyList[x].size() << endl;
					return 0;
				}
	} else {
		for (const int centroidAdjacent : adjacencyList[centroids.first])
			if (centroidAdjacent != centroids.second)
				for (const int adjacentToCentroidAdjacent : adjacencyList[centroidAdjacent])
					if (adjacentToCentroidAdjacent != centroids.first and adjacencyList[adjacentToCentroidAdjacent].size() != 1) {
						cout << ":|" << endl;
						return 0;
					}
		for (const int centroidAdjacent : adjacencyList[centroids.second])
			if (centroidAdjacent != centroids.first)
				for (const int adjacentToCentroidAdjacent : adjacencyList[centroidAdjacent])
					if (adjacentToCentroidAdjacent != centroids.second and adjacencyList[adjacentToCentroidAdjacent].size() != 1) {
						cout << ":|" << endl;
						return 0;
					}
	}
	cout << transformations.size() << '\n';
	for (Transformation& transformation : transformations)
		cout << transformation.x << ' ' << transformation.y << ' ' << transformation.yp << '\n';
	return 0;
}

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long

using namespace std;

const int N = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

int n, last, start, who, sum[N];
vector<int> G[N];
vector<pair<int,PII>> ans;

PII getCenter(int u, int fa) {
    PII tmp = mk(inf, u);
    sum[u] = 1;
    int mx = 0;
    for(int v : G[u]) {
        if(v == fa) continue;
        tmp = min(tmp, getCenter(v, u));
        sum[u] += sum[v];
        mx = max(mx, sum[v]);
    }
    mx = max(mx, n-sum[u]);
    return min(tmp, mk(mx, u));
}

void work(int u, int fa) {
    sum[u] = 1;
    for(int v : G[u]) if(v != fa)
        work(v, u), sum[u] += sum[v];
}

void dfs(int u, int fa) {
    if(fa != who) {
        ans.push_back(mk(who, mk(last, u)));
        ans.push_back(mk(u, mk(fa, start)));
        last = u;
    }
    for(int v : G[u])
        if(v != fa) dfs(v, u);
}

void solve(int u, int fa) {
    who = u;
    for(int v : G[u]) {
        start = v;
        last = v;
        dfs(v, u);
        ans.push_back(mk(u, mk(last, v)));
    }
}

int main() {
    scanf("%d", &n);
    for(int i = 1; i < n; i++) {
        int u, v; scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    int root = getCenter(1, 0).se, root2 = -1;
    work(root, 0);
    for(int v : G[root])
        if(n % 2 == 0 && sum[v] == n/2)
            root2 = v;
    if(~root2) solve(root, root2), solve(root2, root);
    else solve(root, 0);
    printf("%d\n", ans.size());
    for(auto t : ans) printf("%d %d %d\n", t.fi, t.se.fi, t.se.se);
    return 0;
}

/*
*/

#include <bits/stdc++.h>

#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()

using namespace std;

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

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }

template<typename T> T inf;
template<> constexpr int inf<int> = 1e9;
template<> constexpr ll inf<ll> = 1e18;
template<> constexpr ld inf<ld> = 1e30;

struct yes_no : numpunct<char> {
  string_type do_truename()  const { return "Yes"; }
  string_type do_falsename() const { return "No"; }
};

set<int> g[201000];
bool visited[201000];
int cnt[201000];

int dfs1(int v) {
  visited[v] = true;
  int res = 1;
  for (int i: g[v]) {
    if (visited[i]) continue;
    res += dfs1(i);
  }
  return cnt[v] = res;
}

int dfs2(int v, int n) {
  visited[v] = true;
  for (int i: g[v]) {
    if (visited[i]) continue;
    if (cnt[i] * 2 > n) return dfs2(i, n);
  }
  return v;
}

vector<tuple<int,int,int>> res;

pair<int,int> dfs3(int p, int v) {
  visited[v] = true;
  vector<int> ls;
  vector<int> is;
  for (int i: g[v]) {
    if (visited[i]) continue;
    auto ret = dfs3(v, i);
    is.push_back(ret.second);
    ls.push_back(ret.first);
  }
  if (is.empty()) return make_pair(v, v);
  res.emplace_back(p, v, ls[0]);
  REP(i,is.size() - 1) res.emplace_back(is[i], v, ls[i + 1]);
  // cout << "func " << p << " " << v << " " << ls[0] << " " << is.back() << endl;
  return make_pair(v, is.back());
}

void dfs_master(int v, int n) {
  visited[v] = true;
  for (int i: g[v]) {
    if (visited[i]) continue;
    // cout << "cnt " << i << " " << cnt[i] << " " << n << endl;
    if (cnt[i] * 2 >= n) dfs_master(i, n);
    else {
      // cout << "dfs3 " << v << " " << i << endl;
      dfs3(v, i);
    }
  }
}

int dfs4(int v) {
  visited[v] = true;
  int cand = v;
  for (int i: g[v]) {
    if (visited[i]) continue;
    cand = dfs4(i);
    res.emplace_back(v, i, cand);
  }
  return cand;
}

void dfs_master2(int v, int n) {
  visited[v] = true;
  for (int i: g[v]) {
    if (visited[i]) continue;
    if (cnt[i] * 2 >= n) dfs_master2(i, n);
    else {
      int cand = dfs4(i);
      res.emplace_back(v, i, cand);
    }
  }
}

int main() {
  locale loc(locale(), new yes_no);
  cout << boolalpha;
  cout.imbue(loc);
  int n;
  scanf("%d", &n);
  REP(i,n-1) {
    int s, t;
    scanf("%d%d", &s, &t);
    --s; --t;
    g[s].insert(t);
    g[t].insert(s);
  }
  memset(visited, 0, sizeof(visited));
  dfs1(0);
  memset(visited, 0, sizeof(visited));
  const int root = dfs2(0, n);
  memset(visited, 0, sizeof(visited));
  dfs1(root);
  // REP(i,n) cout << cnt[i] << " "; cout << endl;

  memset(visited, 0, sizeof(visited));
  dfs_master(root, n);
  for (auto t: res) {
    int x, y, z;
    tie(x, y, z) = t;
    g[x].erase(y);
    g[y].erase(x);
    g[x].insert(z);
    g[z].insert(x);
  }

  memset(visited, 0, sizeof(visited));
  dfs1(root);
  memset(visited, 0, sizeof(visited));
  dfs_master2(root, n);

  cout << res.size() << endl;
  for (auto t: res) {
    int x, y, z;
    tie(x, y, z) = t;
    cout << x + 1 << " " << y + 1 << " " << z + 1 << endl;
  }
  return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef double D;
typedef long long int LL;

#define st first
#define nd second
#define pb push_back
#define PLL pair <LL, LL>
#define PII pair <int, int>
#define PIII pair <PII, int>

const int N = 2e5 + 7;
const int MX = 1e9 + 7;
const int inf = 1e9 + 9;

int n, m;
int pod[N];
bool block[N];
vector <int> G[N];
vector <PIII> res;

int dfs(int u, int p){
	pod[u] = 1;
	for(int v: G[u])
		if(v != p && !block[v])
			pod[u] += dfs(v, u);
	return pod[u];
}

PII centroid(int u){
	dfs(u, u);
	int par = u;
	int half = (pod[u] + 1) / 2;
	bool even = (pod[u] & 1) ? 0 : 1;

	bool change = true;
	while(change){
		change = false;
		for(int v: G[u])
			if(pod[v] >= half && !block[v] && v != par){
				change = true;
				par = u;
				u = v;
				break;
			}
	}

	if(pod[u] == half && even)
		return {u, par};
	return {u, -1};
}

void add(vector <PIII> &cur, vector <PIII> plus){
	for(auto v: plus)
		cur.pb(v);
}

vector <PIII> Rozbicie(int u, int p){
	PII cur = centroid(u);
//	printf("%d %d -> %d %d\n", u, p, cur.st, cur.nd);
	if(cur.nd == -1){
		vector <PIII> ret;
		block[cur.st] = true;

		if(p != -1 && u != cur.st)
			ret.pb({{p, u}, cur.st});

		for(int v: G[cur.st]){
			if(block[v])	continue;
			add(ret, Rozbicie(v, cur.st));
		}

		return ret;
	}
	else{
		block[cur.st] = true;
		vector <PIII> ret = Rozbicie(u, p);
		block[cur.st] = false;
		add(ret, Rozbicie(cur.st, ret.size() == 0 ? u : ret[0].nd));
		return ret;
	}
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i < n; ++i){
		int u, v;
		scanf("%d %d", &u, &v);
		G[u].pb(v);
		G[v].pb(u);
	}

	res = Rozbicie(1, -1);
	printf("%d\n", (int)res.size());
	for(int i = 0; i < (int)res.size(); ++i)
		printf("%d %d %d\n", res[i].st.st, res[i].st.nd, res[i].nd);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int oo = 1000000001;
const int N = 200011;

vector< pair<int,pii > > fn;

int n,curSZ,sz[N];
bool block[N];
pii E[N];
vector<int> g[N];

void pre(int u,int p = -1){
	sz[u]=1;
	for (int i = 0; i < g[u].size(); ++i){
		int v = g[u][i];
		if(v == p || block[v])continue;
		pre(v,u);
		sz[u] += sz[v];
	}
}
int findCen(int u,int p=-1){
	int mx = -1 , at = -1;
	for (int i = 0; i < g[u].size(); ++i){
		int v = g[u][i];
		if(v == p || block[v])continue;
		at = max(at,findCen(v,u));
		mx = max(mx,sz[v]);
	}
	mx = max(mx,curSZ - sz[u]);
	if(mx * 2 <= curSZ)
		at = u;
	return at;
}
int calc(int u){
	pre(u);
	curSZ = sz[u];
	int cen = findCen(u);
	block[cen] = 1;
	if(cen == -1)cen = u;
	for (int i = 0; i < g[cen].size(); ++i){
		int v = g[cen][i];
		if(block[v])continue;
		int go = calc(v);
		if(go != v)
			fn.push_back(make_pair(cen,make_pair(v,go)));
	}
	return cen;
}
int main() {
	//freopen("input.txt", "r", stdin);
	scanf("%d",&n);
	for (int i = 0; i < n-1; ++i){
		scanf("%d%d",&E[i].first,&E[i].second);
		g[E[i].first].push_back(E[i].second);
		g[E[i].second].push_back(E[i].first);
	}
	calc(1);
	printf("%d\n",(int)fn.size() );
	for (int i = 0; i < fn.size(); ++i){
		printf("%d %d %d\n",fn[i].first,fn[i].second.first,fn[i].second.second);
	}
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

const int INF = (int) 1e9 + 123;
const ll LINF = (ll) 1e18 + 123;
const ld EPS = (ld) 1e-12;
const ll MOD = (ll) 1e9 + 7;

#define sz(x) (int) (x).size()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define lb(s, t, x) (int) (lower_bound(s, t, x) - s)
#define ub(s, t, x) (int) (upper_bound(s, t, x) - s)
#define rep(i, f, t) for (auto i = f; i < t; i++)
#define per(i, f, t) for (auto i = f; i >= t; i--)

ll power(ll x, ll y, ll mod = MOD) {
    if (y == 0) {
        return 1;
    }
    if (y & 1) {
        return power(x, y - 1, mod) * x % mod;
    } else {
        ll tmp = power(x, y / 2, mod);
        return tmp * tmp % mod;
    }
}

inline void add(ll &x, ll y, ll mod = MOD) {
    x += y;
    if (x >= mod) x -= mod;
    if (x < 0) x += mod;
}

inline ll sum(ll x, ll y, ll mod = MOD) {
    add(x, y, mod);
    return x;
}

inline ll mult(ll x, ll y, ll mod = MOD) {
    return (x * y) % mod;
}

inline ll div(ll x, ll y, ll mod) {
    return x * power(y, mod - 2, mod);
}

template<typename A, typename B> inline bool mini(A &x, const B &y) {
    if (y < x) {
        x = y;
        return true;
    }
    return false;
}

template<typename A, typename B> inline bool maxi(A &x, const B &y) {
    if (y > x) {
        x = y;
        return true;
    }
    return false;
}

template<typename T> inline void read(T first, T last) {
    while (first != last) {
        cin >> *(first++);
    }
}

template<typename T> inline void print(T first, T last) {
    while (first != last) {
        cout << *(first++) << " ";
    }
    cout << "\n";
}

void run();

#define TASK ""

int main() {
#ifdef LOCAL
    if (strlen(TASK) > 0) {
        cerr << "Reminder: you are using file i/o, filename: " TASK "!" << endl << endl;
    }
#endif
#ifndef LOCAL
    if (strlen(TASK)) {
        freopen(TASK ".in", "r", stdin);
        freopen(TASK ".out", "w", stdout);
    }
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif
    cout << fixed << setprecision(12);
    run();
    return 0;
}

// == SOLUTION == //

const int N = (int) 2e5 + 123;

struct Q {
    int x, y1, y2;
};

int n;
vector<pair<int, int>> g[N];
vector<Q> res;
bool vis[N], used[N];
int cnt[N];

void calc_cnt(int v, int p = -1) {
    cnt[v] = 1;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || u == p || used[e.second]) continue;
        calc_cnt(u, v);
        cnt[v] += cnt[u];
    }
}

int dfs(int v);

pair<bool, int> centroid_edge(int v, int all, int p = -1) {
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || u == p || used[e.second]) continue;
        auto tmp = centroid_edge(u, all, v);
        if (tmp.first) return tmp;
        if (2 * cnt[u] == all) {
            used[e.second] = 1;
            dfs(v);
            dfs(u);
            return {1, u};
        }
    }
    return {0, -1};
}

void find_centroid(int v, int all, int &x, int p = -1) {
    bool ok = 1;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || used[e.second]) continue;
        ok &= 2 * (u != p ? cnt[u] : all - cnt[v]) < all;
        if (u == p) continue;
        find_centroid(u, all, x, v);
    }
    if (ok) {
        assert(x == -1);
        x = v;
    }
}

int dfs(int v) {
    calc_cnt(v);
    auto tmp = centroid_edge(v, cnt[v]);
    if (tmp.first) {
        return tmp.second;
    }

    int centroid = -1;
    find_centroid(v, cnt[v], centroid);
    assert(centroid != -1);
    v = centroid;
    vis[v] = 1;
    for (auto &e : g[v]) {
        int u = e.first;
        if (vis[u] || used[e.second]) continue;
        res.push_back({v, u, dfs(u)});
    }
    return v;
}

void run() {
    cin >> n;
    rep(i, 0, n - 1) {
        int u, v;
        cin >> u >> v;
        g[u].pb({v, i});
        g[v].pb({u, i});
    }

    dfs(1);

    cout << sz(res) << "\n";
    for (Q &q : res) {
        cout << q.x << " " << q.y1 << " " << q.y2 << "\n";
    }
}

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

using namespace std;
//using namespace __gnu_pbds;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
//typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;

#define FOR(i, a, b) for (int i=a; i<b; i++)
#define F0R(i, a) for (int i=0; i<a; i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)

#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
double PI = 4*atan(1);

int n, sub[200001], par[200001], centr[200001], cen = 1;
vi adj[200001];
vector<pair<int,pii>> ans;

void dfs(int node) {
    sub[node] = 1;
    for (int i: adj[node]) if (i != par[node]) {
        par[i] = node;
        dfs(i);
        sub[node] += sub[i];
    }
}

void dfs1(int node) {
    pii bes = {-1,-1};
    for (int i: adj[node]) if (i != par[node]) {
        dfs1(i);
        bes = max(bes,{sub[i],centr[i]});
    }
    centr[node] = node;
    if (bes.f*2 > sub[node] && n > sub[node]*2) {
        centr[node] = bes.s;
        ans.pb({par[node],{node,centr[node]}});
    }
}

int main() {
    cin >> n;
    F0R(i,n-1) {
        int a,b; cin >> a >> b;
        adj[a].pb(b), adj[b].pb(a);
    }

    dfs(1);
    while (1) {
        bool f = 0;
        for (int i: adj[cen]) if (i != par[cen] && 2*sub[i] > n) {
            cen = i;
            f = 1;
            break;
        }
        if (!f) break;
    }

    par[cen] = 0;
    dfs(cen);
    dfs1(cen);

    cout << ans.size() << "\n";
    for (auto a: ans) cout << a.f << " " << a.s.f << " " << a.s.s << "\n";
}

// read!
// ll vs. int!

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define pb push_back
#define mp make_pair

int n;
set<int> g[200010];
queue<pii> q[200010];
char c[200010];
set<int> centers;
struct tup{
    int x, y, yy, p;
    tup(int x, int y, int yy): x(x), y(y), yy(yy) {}
};
vector<tup> ans;
vector<int> cur;

int mxd, leaf;
int r;

void dfs1(int v, int p, int d){
    if(d > mxd){
        mxd = d;
        leaf = v;
    }
    for(auto to: g[v]){
        if(to != p) dfs1(to, v, d + 1);
    }
}

void dfs2(int v, int p, int d){
    if(d == r){
        centers.insert(v);
        c[v] = true;
    }
    for(auto to: g[v]){
        if(to != p) dfs2(to, v, d + 1);
    }
}

void find_centers(){
    dfs1(0, 0, 0);
    int st = leaf;
    mxd = 0;
    dfs1(st, st, 0);
    r = (mxd + 1) / 2;
    dfs2(st, st, 0);
    dfs2(leaf, leaf, 0);
}

int solve(int v, int p){
    for(auto to: g[v]){
        if(to != p){
            q[v].push(mp(solve(to, v), to));
        }
    }
    while(q[v].size() > 1){
        ans.pb(tup(p, v, q[v].front().first));
        p = q[v].front().second;
        q[v].pop();
    }
    return (q[v].empty()) ? v : q[v].front().first;
}

void solve2(int v, int p){
    cur.pb(v);
    for(auto to: g[v]){
        if(to != p) solve2(to, v);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n;
    for(int i = 0; i < n - 1; i++){
        int from, to;
        cin >> from >> to;
        g[from - 1].insert(to - 1);
        g[to - 1].insert(from - 1);
    }
    find_centers();
    for(auto u: centers){
        for(auto v: g[u]){
            if(c[v]) continue;
            solve(v, u);
        }
    }
    for(tup u: ans){
        g[u.x].erase(u.y);
        g[u.y].erase(u.x);
        g[u.x].insert(u.yy);
        g[u.yy].insert(u.x);
    }
    for(auto u: centers){
        for(auto to: g[u]){
            if(c[to]) continue;
            cur.clear();
            cur.pb(u);
            solve2(to, u);
            cur.pop_back();
            int last = cur.back();
            cur.pop_back();
            for(int i = cur.size() - 1; i >= 1; i--){
                ans.pb(tup(cur[i - 1], cur[i], last));
            }
        }
    }
    assert(ans.size() <= 2 * n);
    cout << ans.size() << endl;
    for(auto u: ans){
        cout << u.x + 1 << ' ' << u.y + 1 << ' ' << u.yy + 1 << endl;
    }
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

#define sqr(x) ((x) * (x))
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define fin(name) freopen(name, "r", stdin)
#define fout(name) freopen(name, "w", stdout)
#define I(x, a) for(auto x : a)
#define F(i, l, r) for(auto i = l; i < r; ++i)
#define E(i, l, r) for(auto i = l; i <= r; ++i)
#define DF(i, l, r) for(auto i = l; i >= r; --i)
#define clean(a) memset((a),0,sizeof (a))
#define sync ios_base::sync_with_stdio(0);cin.tie(0)
#define all(x) (x).begin(),(x).end()
#define ret return
#define cont continue
#define brk break
#define ins insert
#define sz(a) ((int)(a).size())

typedef long long ll;
typedef unsigned long long ull;
typedef long double dbl;
typedef pair <int, int> pii;

const int inf = (int)1e9;
const ll linf = (ll)1e18;
const int mod = (int)1e9 + 7;
const dbl eps = (dbl)1e-8;
const int maxn = (int)2e5 + 5;
const dbl pi = acos(-1);

vector <pair <pii, int>> ans;
int centre, centre2;
vector <int> a[maxn];
set <pii> q;
int sz[maxn], en[maxn];
int n;

void dfs0(int v, int p = -1) {
	int fl = 1;
	sz[v] = 1;
	I(to, a[v]) {
		if (to == p)
			cont;
		dfs0(to, v);
		sz[v] += sz[to];
		if (sz[to] >= n / 2 + n % 2)
			fl = 0;
	}
	if (n - sz[v] <= n / 2 && fl) {
		centre = v;
		centre2 = p;
	}
}

void answer() {
	cout << sz(ans) << endl;
	I(p, ans) {
		cout << p.X.X << " " << p.X.Y << " " << p.Y << "\n";
	}
	exit(0);
}

void upd(int x, int y, int ty) {
	ans.pb({{x, y}, ty});
	q.erase({min(x, y), max(x, y)});
	q.ins({min(x, ty), max(x, ty)});
}

void solve(int v, int p) {
	int cp = p;
	en[v] = v;
	F(i, 0, sz(a[v])) {
		int to = a[v][i];
		if (to == p)
			cont;
		solve(to, v);
		if (i == sz(a[v]) - 1 || (i == sz(a[v]) - 2 && a[v][sz(a[v]) - 1] == p)) {
			en[v] = en[to];
			break;
		}
		int ten = en[to];
		upd(cp, v, ten);
		cp = to;
	}
}

void sol_centre(int centre, int centre2) {
	I(to, a[centre]) {
		if (to != centre2)
			solve(to, centre);
	}
}

void dfs(int v, int p, int z) {
	I(to, a[v]) {
		if (to == p)
			cont;
		dfs(to, v, z);
		if (to != z)
			upd(v, to, z);
	}
}

void sol2_centre(int centre, int centre2) {
	I(to, a[centre]) {
		if (to != centre2) {
			dfs(to, centre, en[to]);
			if (to != en[to])
				upd(centre, to, en[to]);
		}
	}
}

int main() {
//    fin("t.in");
    sync;
	cin >> n;
	q.clear();
	F(i, 0, n - 1) {
		int x, y;
		cin >> x >> y;
		a[x].pb(y);
		a[y].pb(x);
		q.ins({min(x, y), max(x, y)});
	}
	dfs0(1);
	if (sz[centre] == n / 2 && n % 2 == 0) {} else {
		centre2 = -1;
	}
	cout << centre << " " << centre2 << endl;
	ans.clear();
	sol_centre(centre, centre2);
	if (centre2 != -1) {
		sol_centre(centre2, centre);
	}
	E(i, 1, n) {
		a[i].clear();
	}
	I(e, q) {
		a[e.X].pb(e.Y);
		a[e.Y].pb(e.X);
	}
	sol2_centre(centre, centre2);
	if (centre2 != -1) {
		sol2_centre(centre2, centre);
	}

	answer();
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
int n;
const int N = 201000;
vector <int> bi[N];
int siz[N];
int val, mid1, mid2;
void dfs1(int t, int f = 0)
{
    siz[t] = 1;
    int mxc = 0;
    for (int i = 0; i < bi[t].size(); ++ i)
        if (bi[t][i] != f)
        {
            dfs1(bi[t][i], t);
            siz[t] += siz[bi[t][i]];
            if (siz[bi[t][i]] > mxc) mxc = siz[bi[t][i]];
        }
    mxc = max(mxc, n - siz[t]);
    if (mxc < val) val = mxc, mid1 = t, mid2 = 0;
    else if (mxc == val) mid2 = t;
}
vector <int> X, Y, Y_;
void ADD(int x, int y, int y_)
{
    X.push_back(x); Y.push_back(y); Y_.push_back(y_);
    // cerr << x << " " << y << " " << y_ << endl;
}
int nwm, nwc, tar;
void dfs2(int t, int f)
{
    int cnt = 0;
    for (int i = 0; i < bi[t].size(); ++ i)
        if (bi[t][i] != f)
            dfs2(bi[t][i], t), cnt ++;
    if (cnt == 0 && t != tar) ADD(nwm, nwc, t), ADD(t, f, tar), nwc = t;
}
void solve(int mid1, int mid2)
{
    nwm = mid1;
    for (int i = 0; i < bi[mid1].size(); ++ i)
        if (bi[mid1][i] != mid2)
        {
            tar = nwc = bi[mid1][i];
            dfs2(bi[mid1][i], mid1);
            if (nwc != tar) ADD(nwm, nwc, tar);
        }
}
int main()
{
    cin >> n;
    if (n <= 3) {cout << 0; return 0;}
    for (int i = 1; i < n; ++ i)
    {
        int a, b;
        cin >> a >> b;
        bi[a].push_back(b);
        bi[b].push_back(a);
    }
    val = n;
    dfs1(1);
    solve(mid1, mid2);
    solve(mid2, mid1);
    cout << X.size() << endl;
    for (int i = 0; i < X.size(); ++ i)
        cout << X[i] << " " << Y[i] << " " << Y_[i] << endl;
}

#include <bits/stdc++.h>
using namespace std;
#define sqr(x) ((x)*(x))
#define par make_pair
#define pb push_back
#define fi first
#define se second
#define endl '\n'
template<class X, class Y> void amax(X& x, const Y& y){if(x < y) x = y;}
template<class X, class Y> void amin(X& x, const Y& y){if(x > y) x = y;}
typedef vector<int> vi; typedef pair<int, int> ii; typedef long long ll; typedef long double ld;
const int INF = 1e9 + 10; const ll INFL = 1e18 + 10;
const int MAX = 2e5 + 10;

struct op{
    int x, y, z;
};

int n;
vi es[MAX];
int sz[MAX];
ii nxt[MAX];
vector<op> res;

void dfs_dist(int u, int p){
    sz[u] = 1;
    for(auto v : es[u]) if(v != p){
        dfs_dist(v, u);
        sz[u] += sz[v];
    }
}

ii find_centroid(int u, int p){
    for(auto v : es[u]) if(v != p){
        if(sz[v] > n/2) return find_centroid(v, u);
        if(sz[v] == (n + 1)/2) return par(u, v);
    }
    return par(u, 0);
}

void rem_edge(int u, int v){
    if(nxt[u].fi == v) nxt[u].fi = 0;
    if(nxt[u].se == v) nxt[u].se = 0;
    if(nxt[v].fi == u) nxt[v].fi = 0;
    if(nxt[v].se == u) nxt[v].se = 0;
}

void add_edge(int u, int v){
    if(nxt[u].fi == 0) nxt[u].fi = v;
    else nxt[v].se = v;
    if(nxt[v].fi == 0) nxt[v].fi = u;
    else nxt[v].se = u;
}

int get_next(int u, int v){
    if(nxt[u].fi != 0 && nxt[u].fi != v) return nxt[u].fi;
    if(nxt[u].se != 0 && nxt[u].se != v) return nxt[u].se;
    return -1;
}

void add_op(const op &o){
    rem_edge(o.x, o.y);
    add_edge(o.x, o.z);
    if(o.y == o.z) return;
    res.pb(o);
}

int to_bamboo(int u, int p){
    int top = u, start = p;
    for(auto v : es[u]) if(v != p){
        if(top == u) top = v;
        int b = to_bamboo(v, u);
        add_op(op{start, u, v});
        start = b;
    }
    if(top == u) add_edge(u, p);
    return top;
}

void to_star(int u, int p){
    int b = to_bamboo(u, p);
    vi sq; sq.pb(p); sq.pb(b);
    int prv = p;
    while(true){
        int v = get_next(b, prv);
        if(v == -1) break;
        sq.pb(v);
        prv = b;
        b = v;
    }

    //~ if(u == 3){
        //~ for(auto x : sq) cout << x << " ";
        //~ cout << endl;
        //~ exit(0);
    //~ }

    int cen = sq[(int)sq.size() - 2];
    for(int i = (int)sq.size() - 4; i >= 0; i--) add_op(op{sq[i], sq[i + 1], cen});
}

void process(){
    cin >> n;
    for(int i = 1; i < n; i++){
        int u, v; cin >> u >> v;
        es[u].pb(v); es[v].pb(u);
    }
    dfs_dist(1, 0);
    ii c = find_centroid(1, 0);
    //cout << c.fi << " " << c.se << endl;
    for(auto v : es[c.fi]) if(v != c.se) to_star(v, c.fi);
    for(auto v : es[c.se]) if(v != c.fi) to_star(v, c.se);
    cout << res.size() << endl;
    for(auto v : res) cout << v.x << " " << v.y << " " << v.z << endl;
}

int main(){
    ios_base::sync_with_stdio(false);
    //cin.tie(NULL);
    //freopen("c.in", "r", stdin);
    process();
}

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

#define F first
#define S second
#define int long long
#define ull  unsigned long long
#define pb push_back

using namespace std;
using namespace __gnu_pbds;
typedef  tree< int , null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

const int N = 100002;
int val[N], nxt[N], cntr[N], r, sc, d;
vector < int > g[N], q, c;
set < int > s[N];
int f[N];
int z;
vector < pair < int, pair < int, int > > > ans;
void dfs1(int v, int p = -1){
    for (auto u: g[v]){
        if (u == p) continue;
        dfs1(u, v);
    }
    if (g[v].size() == 1){
        s[0].insert(v);
        f[v] = 1;
    }
}
void dfs2(int v, int p = -1){
    if (p != r){
        ans.pb({r, {d, v}});
        ans.pb({v, {p, sc}});
    }
    d = v;
    for (auto u: g[v]){
        if (u == p) continue;
        dfs2(u, v);
    }
}
main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    //freopen("input.txt",  "r", stdin);
    //freopen("output.txt", "w", stdout);
    int n;
    cin >> n;
    for (int i = 1; i < n; i++){
        int u, v;
        cin >> u >> v;
        g[u].pb(v);
        g[v].pb(u);
    }
    dfs1(1);
    z += s[0].size();
    for (int i = 0; i <= n; i++){
        if (s[i].size() == 1 || (s[i].size() == 2 && z == n)){
            for (auto j: s[i]){
                c.pb(j);
                cntr[j] = 1;
            }
            break;
        }
        for (auto j: s[i]){
            for (auto u: g[j]) if (!f[u]){
                s[i + 1].insert(u);
                f[u] = 1;
            }
        }
        z += s[i + 1].size();
    }
    for (auto v: c){
        r = v;
        for (auto u: g[v]){
            if (cntr[u]) continue;
            sc = u;
            d = sc;
            dfs2(u, v);
            ans.pb({v, {d, u}});
        }
    }
    cout << ans.size() << endl;
    if (ans.size() * 2 > n){
        n /= 0;
        return 0;
    }
    for (auto i: ans){
        cout << i.F << " " << i.S.F << " " << i.S.S << endl;
    }
}

#pragma comment(linker, "/STACK:204800000,204800000")
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
#include <functional>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <sstream>
#include <unordered_set>
#include <unordered_map>
#include <sstream>
#include <set>
#include <cassert>
using namespace std;

//ifstream in("C:\\input.txt");
istream& in = cin;
struct Node{
	int x, y1, y2;
	Node(int a, int b, int c){
		x = a;
		y1 = b;
		y2 = c;
	}
};

#define pii pair<int,int>
#define mp make_pair
#define pb push_back
typedef long long LL;
#define MMAX ((int)2e5+10)
vector<Node> ans;
vector<int> edge[MMAX];
int dfs(int p,int f){
	if (edge[p].size() == 1){
		return p;
	}
	int ret;
	for (int son : edge[p]){
		if (son == f)
			continue;
		ret = dfs(son, p);
		ans.push_back(Node(p, son, ret));
	}
	return ret;
}

int n;
vector<int> vi[MMAX];

int pre_dfs(int p, int f, bool root){
	if (vi[p].size() == 1){
	//	edge[p].pb(f);
	//	edge[f].pb(p);
		return p;
	}
	vector<pii> leaf;
	for (int son : vi[p]){
		if (son == f)
			continue;
		leaf.pb(mp(pre_dfs(son, p, 0),son));
	}

	if (root){
		for (int i = 0; i < leaf.size(); ++i){
			edge[vi[p][i]].push_back(p);
			edge[p].push_back(vi[p][i]);

		}
		return -1;
	}
	else{

		if (p == 7){
			int t = 0;
		}

		if (leaf.size() == 1){

			edge[p].push_back(leaf[0].second);
			edge[leaf[0].second].push_back(p);
			return leaf[0].first;
		}
		else{

			ans.push_back(Node(f, p, leaf.back().first));
			int nowf = leaf.back().second;
			int nowp = p;
			for (int i = leaf.size() - 2; i >= 0; --i){
				ans.push_back(Node(nowf, nowp, leaf[i].first));

				edge[leaf[i].first].push_back(nowf);
				edge[nowf].push_back(leaf[i].first);
				nowf = leaf[i].second;
				nowp = p;

			}
			edge[p].push_back(nowf);
			edge[nowf].push_back(p);
		}
		return p;
	}
}

void input(){
	in >> n;
	for (int i = 1; i < n; ++i){
		int a, b;
		in >> a >> b;
		vi[a].pb(b);
		vi[b].pb(a);
	}
}
bool ok[MMAX];
int roota, rootb;
int get_root(int p,int f){
	int size = 1;
	for (int son : vi[p]){
		if (son == f)
			continue;
		size += get_root(son, p);
	}

	if (size < n - size){
		ok[p] = 1;
	}

	if ( f != -1 && n - size < size ){
		ok[f] = 1;
	}
	return size;
}

int main(){

	int TEST_CASE = 1;
	//in >> TEST_CASE;
	while (TEST_CASE-- > 0){
		input();
		if (n <= 3){
			cout << 0 << endl;
			continue;
		}
		roota = rootb = -1;

		get_root(1, -1);
		vector<int> vp;
		for (int i = 1; i <= n;++i)
		if (!ok[i])
			vp.push_back(i);

		assert(vp.size() <= 2);

		roota = vp[0];
		if (vp.size() == 2){
			rootb = vp.back();
		}

		pre_dfs(roota, rootb, 1);
		if (rootb != -1){
			pre_dfs(rootb, roota, 1);
		}

		dfs(roota, -1);
		if (rootb != -1){
			dfs(rootb, -1);
		}

		printf("%d\n", ans.size());
		for (Node& p : ans){
			printf("%d %d %d\n", p.x, p.y1, p.y2);
		}

	}

	return 0;
}

#include <bits/stdc++.h>
using namespace std;
const int maxn=2*100000+5;
#define MP make_pair
vector<int > g[maxn];
void addedge(int from,int to)
{
	g[from].push_back(to);
	g[to].push_back(from);
}
int n;
int siz[maxn],pa[maxn];
vector<pair<int ,pair<int ,int > > > Rlt;
pair<int ,int > FindCent(int v,int fa,int N)
{
	pa[v]=fa;
	pair<int ,int > Res=MP(N,-1);
	siz[v]=1;
	int maxsiz=0;
	for(int i=0;i<(int)g[v].size();i++){
		int u=g[v][i];
		if(u!=fa){
			Res=min(Res,FindCent(u,v,N));
			siz[v]+=siz[u];
			maxsiz=max(maxsiz,siz[u]);
		}
	}
	maxsiz=max(maxsiz,N-siz[v]);
	Res=min(Res,MP(maxsiz,v));
	return Res;
}
vector<pair<int ,int > > topo;
void dfs(int v,int fa)
{
	for(int i=0;i<(int)g[v].size();i++){
		int u=g[v][i];
		if(u!=fa) dfs(u,v);
	}
	topo.push_back(MP(v,fa));
}
void Getrlt(int v,int fa)
{
	topo.clear();
	dfs(v,fa);
	topo.pop_back();
	int iter=v;
	for(int i=0;i<(int)topo.size();i++){
		if(iter!=topo[i].first)
			Rlt.push_back(MP(fa,MP(iter,topo[i].first)));
		if(topo[i].second!=v)
			Rlt.push_back(MP(topo[i].first,MP(topo[i].second,v)));
		iter=topo[i].first;
	}
	if(iter!=v) Rlt.push_back(MP(fa,MP(iter,v)));
}
int main()
{
	//freopen("1.in","r",stdin);
	scanf("%d",&n);
	for(int i=0;i<n-1;i++){
		int from,to;
		scanf("%d%d",&from,&to);
		g[from].push_back(to);
		g[to].push_back(from);
	}
	pair<int ,int > cent=FindCent(1,-1,n),cent2=MP(0,0);
	//printf("Cent: siz=%d v=%d\n",cent.first,cent.second);
	for(int i=1;i<=n;i++){
		if(i!=cent.second && siz[i]*2==n) cent2=MP(siz[i],i);
	}
	//for(int i=1;i<=n;i++){printf("siz[%d]=%d\n",i,siz[i]);}puts("");
	//printf("Cent2: siz=%d v=%d\n",cent2.first,cent2.second);
	for(int i=0;i<(int)g[cent.second].size();i++){
		int u=g[cent.second][i];
		if(u!=cent2.second) Getrlt(u,cent.second);
	}
	if(cent2!=MP(0,0))
		for(int i=0;i<(int)g[cent2.second].size();i++){
			int u=g[cent2.second][i];
			if(u!=cent.second) Getrlt(u,cent2.second);
		}
	printf("%d\n",Rlt.size());
	for(int i=0;i<(int)Rlt.size();i++){
		printf("%d %d %d\n",Rlt[i].first,Rlt[i].second.first,Rlt[i].second.second);
	}
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define sqr(x) ((x)*(x))
#define par make_pair
#define pb push_back
#define fi first
#define se second
#define endl '\n'
template<class X, class Y> void amax(X& x, const Y& y){if(x < y) x = y;}
template<class X, class Y> void amin(X& x, const Y& y){if(x > y) x = y;}
typedef vector<int> vi; typedef pair<int, int> ii; typedef long long ll; typedef long double ld;
const int INF = 1e9 + 10; const ll INFL = 1e18 + 10;
const int MAX = 2e5 + 10;

struct op{
    int x, y, z;
};

int n, moment, trsz;
vi es[MAX];
vector<op> res;
bool mark[MAX];
int sz[MAX];

void add_op(const op &x){
    if(x.x < 1 || x.y < 1 || x.z < 1 || x.y == x.z) return;
    res.pb(x);
}

ii dfs_centroid(int u, int p){
    for(auto v : es[u])
    if(!mark[v] && v != p){
        if(sz[v] > trsz/2) return dfs_centroid(v, u);
        if(sz[v] == (trsz + 1)/2) return par(u, v);
    }
    return par(u, 0);
}

void dfs_size(int u, int p){
    sz[u] = 1;
    for(auto v : es[u]) if(!mark[v] && v != p){
        dfs_size(v, u);
        sz[u] += sz[v];
    }
}

void find_centroid(int u, int pc){
    dfs_size(u, 0);
    trsz = sz[u];
    ii x = dfs_centroid(u, 0);
    add_op(op{pc, u, x.fi});
    mark[x.fi] = true;
    if(u == 1) mark[x.se] = true;
    for(auto v : es[x.fi]) if(!mark[v]) find_centroid(v, x.fi);
    if(u == 1) for(auto v : es[x.se]) if(!mark[v]) find_centroid(v, x.se);
}

void process(){
    cin >> n;
    for(int i = 1; i < n; i++){
        int u, v; cin >> u >> v;
        es[u].pb(v); es[v].pb(u);
    }

    find_centroid(1, 0);
    cout << res.size() << endl;
    for(auto v : res) cout << v.x << " " << v.y << " " << v.z << endl;
}

int main(){
    ios_base::sync_with_stdio(false);
    //cin.tie(NULL);
    //freopen("c.in", "r", stdin);
    process();
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define pb push_back
#define mp make_pair

int n;
set<int> g[200010];
deque<pii> q[200010];
char c[200010];
set<int> centers;
struct tup{
    int x, y, yy, p;
    tup(int x, int y, int yy): x(x), y(y), yy(yy) {}
};
vector<tup> ans;
queue<tup> tmp;
vector<int> cur;
int d[200010];

void dfs1(int v, int p){
    for(auto to: g[v]){
        if(to != p){
            dfs1(to, v);
            d[v] += d[to];
        }
    }
    d[v]++;
}

void find_centers(){
    dfs1(0, 0);
    for(int i = 0; i < n; i++){
        bool canCenter = true;
        for(auto to: g[i]){
            int cursz;
            if(d[to] < d[i]) cursz = d[to];
            else cursz = n - d[i];
            if(cursz > n / 2) canCenter = false;
        }
        if(canCenter){
            c[i] = true;
            centers.insert(i);
        }
    }
}

void freeQ(){
    while(!tmp.empty()){
        tup u = tmp.front();
        tmp.pop();
        g[u.x].erase(u.y);
        g[u.y].erase(u.x);
        g[u.x].insert(u.yy);
        g[u.yy].insert(u.x);
        cout << u.x + 1 << ' ' << u.y + 1 << ' ' << u.yy + 1 << endl;
    }
}

int go(int v, int p){
    for(auto to: g[v]){
        if(to != p) return go(to, v);
    }
    return v;
}

pii solve(int v, int p){
    vector<int> t;
    for(auto to: g[v]) if(to != p) t.pb(to);
    int lo, hi;
    if(t.empty()) lo = hi = v;
    for(auto to: t){
        q[v].push_back(solve(to, v));
        //cout << v + 1 << ' ' << to + 1 << ' ' << q[v].back().first + 1 << ' ' << q[v].back().second + 1 << endl;

    }
    if(!q[v].empty()){
        if(q[v].size() != 1) lo = q[v].front().first;
        else lo = v;
        hi = q[v].back().first;
    }
    while(q[v].size() > 1){
        ans.pb(tup(p, v, q[v].front().first));
        tmp.push(tup(p, v, q[v].front().first));
        p = q[v].front().second;
        q[v].pop_front();
    }
    freeQ();
    return mp(hi, lo);
}

void solve2(int v, int p){
    cur.pb(v);
    for(auto to: g[v]){
        if(to != p) solve2(to, v);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n;
    for(int i = 0; i < n - 1; i++){
        int from, to;
        cin >> from >> to;
        g[from - 1].insert(to - 1);
        g[to - 1].insert(from - 1);
    }
    find_centers();
    for(auto u: centers){
        vector<int> t;
        for(auto v: g[u]) if(!c[v]) t.pb(v);
        for(auto v: t){
            solve(v, u);
            freeQ();
        }
    }
    /*cout << endl;
    for(int i = 0; i < n; i++){
        for(auto to: g[i]){
            if(i < to) cout << i + 1 << ' ' << to + 1 << endl;
        }
    }*/
    for(auto u: centers){
        for(auto to: g[u]){
            if(c[to]) continue;
            cur.clear();
            cur.pb(u);
            solve2(to, u);
            cur.pop_back();
            int last = cur.back();
            cur.pop_back();
            for(int i = (int)cur.size() - 1; i >= 1; i--){
                ans.pb(tup(cur[i - 1], cur[i], last));
            }
        }
    }
    cout << ans.size() << endl;
    for(auto u: ans){
        cout << u.x + 1 << ' ' << u.y + 1 << ' ' << u.yy + 1 << endl;
    }
    return 0;
}

#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
int N, M;
vector <int> G[200005];
int Sz[200005], Size[200005];
int sum, cnt;
bool Blocked[200005];
struct Solution{
int x, y, y2;
} S[400005];
bool first;
void Read()
{
    scanf("%d", &N);
    for(int i = 2; i <= N; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
}

void DFS(int node, int father)
{
    Sz[node] = 1;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        DFS(neighb, node);
        Sz[node] += Sz[neighb];
    }
}

int findCentroid(int node, int father, int size)
{
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        if(Sz[neighb] > size / 2)
            return findCentroid(neighb, node, size);
    }
    return node;
}

int centroidDecompose(int root)
{
    DFS(root, 0);
    int center = findCentroid(root, 0, Sz[root]);
    Blocked[center] = 1;
    int sz = Sz[root];
    bool ok = 0;
    if(first == 0)
    {
        for(int i = 1; i <= N; i++)
        Size[i] = Sz[i];
        first = 1;
        ok = 1;
    }

    int node = center;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        int from = center;
        if(Blocked[neighb] == 1)
            continue;

        int n = centroidDecompose(neighb);
        if(n == neighb || n == from)
            continue;
        ++cnt;
        S[cnt].x = node;
        S[cnt].y = neighb;
        S[cnt].y2 = n;
    }
    return center;
}
int main()
{
    Read();
    int root = 1;
    DFS(root, 0);
    bool ok = 0;
    int center = findCentroid(root, 0, Sz[root]);
    for(int i = 0; i < G[center].size(); i++)
    {
        int neighb = G[center][i];
        if(Sz[neighb] == N - Sz[neighb])
        {
            /*for(auto it = G[neighb].begin(); it != G[neighb].end(); it = next(it))
                if(*it == center)
                {
                    G[neighb].erase(it);
                    break;
                }

            swap(G[center][i], G[center][G[center].size() - 1]);
            G[center].pop_back();*/
            ok = 1;
            Blocked[center] = 1;
            Blocked[neighb] = 1;
            int node = center;
            for(int i = 0; i < G[node].size(); i++)
            {
                int neighb = G[node][i];
                int from = center;
                if(Blocked[neighb] == 1)
                    continue;

                int n = centroidDecompose(neighb);
                if(n == neighb || n == node)
                    continue;
                ++cnt;
                S[cnt].x = node;
                S[cnt].y = neighb;
                S[cnt].y2 = n;
            }
            node = neighb;
            for(int i = 0; i < G[node].size(); i++)
            {
                int neighb = G[node][i];
                int from = center;
                if(Blocked[neighb] == 1)
                    continue;

                int n = centroidDecompose(neighb);
                if(n == neighb || n == node)
                    continue;
                ++cnt;
                S[cnt].x = node;
                S[cnt].y = neighb;
                S[cnt].y2 = n;
            }
            break;
        }
    }
    if(ok == 0)
        centroidDecompose(1);
    printf("%d\n", cnt);
    for(int i = cnt; i >= 1; i--)
    {
        printf("%d %d %d\n", S[i].x, S[i].y, S[i].y2);
    }
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
vector<int> v[200010],c[200010],rt;
int n,siz[200010],fa[200010],dep[200010];
vector<pair<int,pair<int,int> > > ans;
void dfs1(int np,int fath)
{
	bool isrt=1;
	siz[np]=1;
	for(int x:v[np])
	{
		if(x==fath)continue;
		dfs1(x,np);
		siz[np]+=siz[x];
		if(siz[x]>(n>>1))isrt=0;
	}
	if(n-siz[np]>(n>>1))isrt=0;
	if(isrt)rt.push_back(np);
}
int stk[200010],top;
void dfs2(int np,int fath)
{
	fa[np]=fath;
	stk[top++]=np;
	if(dep[np]>=3)
		c[stk[1]].push_back(np);
	for(int x:v[np])
	{
		if(x==fath)continue;
		dep[x]=dep[np]+1;
		dfs2(x,np);
	}
	top--;
}
int main()
{
	scanf("%d",&n);
	for(int i=1,ti,tj;i<n;i++)
	{
		scanf("%d%d",&ti,&tj);
		v[ti].push_back(tj);
		v[tj].push_back(ti);
	}
	dfs1(1,0);
	if(rt.size()==1)
		dfs2(rt[0],0);
	else
		dfs2(rt[0],rt[1]),dfs2(rt[1],rt[0]);
	for(int i=1;i<=n;i++)if(c[i].size())
	{
		int cur=i;
		for(int p:c[i])
		{
			ans.push_back(make_pair(fa[i],make_pair(i,p))),ans.push_back(make_pair(p,make_pair(fa[p],i)));
			cur=p;
		}
		ans.push_back(make_pair(fa[i],make_pair(cur,i)));
	}
	printf("%d\n",ans.size());
	for(int i=0;i<ans.size();i++)
		printf("%d %d %d\n",ans[i].first,ans[i].second.first,ans[i].second.second);
	return 0;
}

#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
int N, M;
vector <int> G[200005];
int Sz[200005];
int sum, cnt;
bool Blocked[200005];
struct Solution{
int x, y, y2;
} S[200005];
bool first;
void Read()
{
    scanf("%d", &N);
    for(int i = 2; i <= N; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
}

void DFS(int node, int father)
{
    Sz[node] = 1;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        DFS(neighb, node);
        Sz[node] += Sz[neighb];
    }
}

int findCentroid(int node, int father, int size)
{
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        if(Sz[neighb] > size / 2)
            return findCentroid(neighb, node, size);
    }
    return node;
}

int centroidDecompose(int root)
{
    DFS(root, 0);
    int center = findCentroid(root, 0, Sz[root]);
    Blocked[center] = 1;

    int node = center;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(Blocked[neighb] == 1)
            continue;
        int n = centroidDecompose(neighb);
        if(n == neighb)
            continue;
        ++cnt;
        S[cnt].x = center;
        S[cnt].y = neighb;
        S[cnt].y2 = n;
    }
    return center;
}
int main()
{
    Read();
    centroidDecompose(1);
    printf("%d\n", cnt);
    for(int i = 1; i <= cnt; i++)
    {
        printf("%d %d %d\n", S[i].x, S[i].y, S[i].y2);
    }
    return 0;
}

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

typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<VI> VVI;
const int INF = 2000000000;

VVI adj;
PII dfsBamboo(int u, const function<void(int,int,int)> &emit, int p = -1){
	vector<PII> leaves;
	for(int v : adj[u]){
		if(v == p)continue;
		leaves.push_back( dfsBamboo(v, emit, u) );
	}
	if(leaves.size() == 0)return PII(u, u);
	for (int i = 0; i < leaves.size(); ++i) {
		if(i == 0){
			emit(p, u, leaves[i].second);
		}else{
			emit(leaves[i-1].first, u, leaves[i].second);
		}
	}
	return PII(leaves[0].second, u);
}
int dfsStar(int u, const function<void(int,int,int)> &emit, int p = -1) {
	for(int v : adj[u]){
		if(v == p)continue;
		int nch = dfsStar(v, emit, u);
		emit(p, u, nch);
		return nch;
	}
	return u;

}
PII cp(int a, int b){
	return PII(min(a,b), max(a,b));
}
int SZ[200010];
int dfsSize(int u,int p = -1){
	SZ[u] = 1;
	for(int v : adj[u])
		if(v != p)
			SZ[u] += dfsSize(v, u);
	return SZ[u];
}

struct Change {
	int u,v0,v1;
};
int main()
{
	int N;
	cin >> N;
	adj = VVI(N);
	set<PII> S;
	for (int i = 0; i < N-1; ++i) {
		int u,v;
		cin >> u >> v;
		u--;v--;
		S.insert(cp(u,v));
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	dfsSize(0);
	vector<int> CD;

	for (int u = 0; u < N; ++u) {
		int b = 0;
		for(int v : adj[u]){
			int csz = SZ[v] < SZ[u] ? SZ[v] : (N-SZ[v]);
			b = max(b, csz);
		}
		if(b*2 <= N)
			CD.push_back(u);
	}
	vector<Change> CH;
	for(int c : CD){
		for(int v : adj[c]){
			if(find(CD.begin(), CD.end(), v) != CD.end())continue;
			dfsBamboo(v, [&S, &CH](int u, int v0, int v1) {
				S.erase(cp(u,v0));
				S.insert(cp(u,v1));
				CH.push_back({u+1, v0+1, v1+1});
			}, c);
		}
	}
	adj = VVI(N);
	for(PII p : S){
		adj[p.first].push_back(p.second);
		adj[p.second].push_back(p.first);
	}
	for(int c : CD){
		for(int v : adj[c]){
			if(find(CD.begin(), CD.end(), v) != CD.end())continue;
			dfsStar(v, [&S, &CH](int u, int v0, int v1) {
				S.erase(cp(u,v0));
				S.insert(cp(u,v1));
				CH.push_back({u+1, v0+1, v1+1});
			}, c);
		}
	}
	cout << CH.size() << endl;
	for(Change &c : CH)
		cout << c.u << " " << c.v0 << " " << c.v1 << endl;
}

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

int N;
vector<vector<int> > adj;
vector<int> del, sz;

void getSz(int u, int p) {
	sz[u] = 1;
	for(int i = 0; i < adj[u].size(); i++) {
		int v = adj[u][i];
		if(v == p || del[v]) continue;
		getSz(v, u);
		sz[u] += sz[v];
	}
}

int getCent(int u, int p, int tot) {
	for(int i = 0; i < adj[u].size(); i++) {
		int v = adj[u][i];
		if(v == p || del[v]) continue;
		if(sz[v] > tot/2) return getCent(v, u, tot);
	}
	return u;
}

int root;
struct Info {
    int x, y1, y2;
};
vector<Info> ans;

int centDeco(int u) {
	getSz(u, -1);
	int cent = getCent(u, -1, sz[u]);
	del[cent] = 1;

	for(int i = 0; i < adj[cent].size(); i++) {
		int v = adj[cent][i];
		if(del[v]) continue;
		int nxt = centDeco(v);
		ans.push_back({cent, v, nxt});
	}
	return cent;
}

int main() {
    scanf("%d", &N);
    adj.resize(N);
    for(int i = 0; i < N - 1; i++) {
        int u, v; scanf("%d %d", &u, &v);
        u--; v--;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    del = sz = vector<int>(N, 0);
    getSz(0, -1);
    int cent = getCent(0, -1, sz[0]);
    getSz(cent, -1);

    int u = -1;
    for(int i = 0; i < adj[cent].size(); i++) {
        int v = adj[cent][i];
        if(N % 2 == 0 && sz[v] == N / 2) {
            u = v;
            break;
        }
    }

    //cout << cent << ' ' << u << endl;

    if(u != -1) {
        del[u] = 1;
        del[cent] = 1;
        centDeco(u);
        centDeco(cent);
    }
    else centDeco(0);

    printf("%d\n", ans.size());
    for(int i = 0; i < ans.size(); i++) {
        printf("%d %d %d\n", ans[i].x + 1, ans[i].y1 + 1, ans[i].y2 + 1);
    }
}

#include <bits/stdc++.h>

using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ll long long
const int N = 1e6+5;
vector<int>g[N],p,gg[N];
vector<vector<int> >ans;
int size[N],n,f[N]={0},size_p[N]={0},V[N];
map<pair<int,int>,int>m;
vector<int>tmp;
vector<pair<int,int> >tmp1;
int dfs(int u,int fa)
{
	size[u]=1;
	for(auto &v:g[u]){if(v==fa)continue;size[u]+=dfs(v,u);}
	return size[u];
}
void dfs1(int u,int fa)
{
	for(auto &v:g[u]){if(v==fa)continue;dfs1(v,u);}
	int ma=n-size[u];
	for(auto &v:g[u]){if(v==fa)continue;ma=max(ma,size[v]);}
	if(ma*2<=n)p.pb(u);
}
void dfs2(int u,int fa)
{
	for(auto &v:g[u]){if(v==fa||2*size[v]==n)continue;dfs2(v,u);}
	int ff=fa;
	if(fa!=-1&&n-size[u]>size[u])for(auto &v:g[u]){if(v==fa)continue;
		if(!V[u])V[u]=f[v];
		ans.pb({ff,u,f[v]});
		m[{ff,u}]=m[{u,ff}]=0;m[{ff,f[v]}]=m[{f[v],ff}]=1;
		ff=(V[v]==0?v:V[v]);
	}f[u]=u;
}int ffff=0;
int dfs4(int u,int fa)
{
	int t=u;
	for(auto &v:g[u]){if(v==fa)continue;t=dfs4(v,u);}
	if((int)g[u].size()==1)return u;
	if(fa!=-1) ans.pb({fa,u,t});
	if(fa==52650&&u==173727)ffff=1;
	return t;
}
int dfs5(int u,int fa)
{
	int si=1;
	for(auto &v:g[u]){if(v==fa)continue;si+=dfs5(v,u);}
	if(n%2==0){if(si==n/2){tmp1.pb({fa,u});tmp1.pb({u,fa});}}
	else{if(si==n/2+1)tmp1.pb({u,-1});}
	return si;
}
int main()
{
	scanf("%d",&n);memset(V,0,sizeof(V));memset(f,0,sizeof(f));memset(size_p,0,sizeof(size_p));
	for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].pb(v);g[v].pb(u);}
	dfs(1,-1);dfs1(1,-1);
	for(int i=1;i<=n;i++)for(auto &v:g[i])m[{i,v}]=1;
	for(auto &t:p)dfs(t,-1),dfs2(t,-1);
	//for(auto &t:ans)printf("%d %d %d\n",t[0],t[1],t[2] );
	for(int i=1;i<=n;i++)g[i].clear();
	for(auto &t:m)if(t.se){g[t.fi.fi].pb(t.fi.se);size_p[t.fi.se]++;}
	dfs(1,-1);
	for(int i=1;i<=n;i++)if(size_p[i]>2)tmp.pb(i);
	if((int)tmp.size()==0){int tt;
		for(int i=1;i<=n;i++)if(size_p[i]==1){tt=i;break;}
		dfs5(tt,-1);
	}else{p.clear();
		dfs(1,-1);dfs1(1,-1);
		tmp.clear();for(auto &t:p)tmp.pb(t);
		if((int)tmp.size()==1)for(auto &v:g[tmp[0]])tmp1.pb({v,tmp[0]});
		else{
			for(auto &v:g[tmp[0]])if(v!=tmp[1])tmp1.pb({v,tmp[0]});
			for(auto &v:g[tmp[1]])if(v!=tmp[0])tmp1.pb({v,tmp[1]});
		}
	}
	for(auto &t:tmp1)dfs4(t.fi,t.se);
	if(ffff)for(auto &t:tmp1)printf("--%d %d\n",t.fi,t.se );
	printf("%d\n",(int)ans.size() );
	for(auto &t:ans)printf("%d %d %d\n",t[0],t[1],t[2] );
	return 0;
}
/*
10
1 4
1 5
1 6
1 2
2 10
10 3
3 7
3 8
3 9
*/

#pragma comment(linker, "/STACK:204800000,204800000")
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
#include <functional>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <sstream>
#include <unordered_set>
#include <unordered_map>
#include <sstream>
#include <set>
#include <cassert>
using namespace std;

//ifstream in("C:\\input.txt");
istream& in = cin;
struct Node{
	int x, y1, y2;
	Node(int a, int b, int c){
		x = a;
		y1 = b;
		y2 = c;
	}
};

#define pii pair<int,int>
#define mp make_pair
#define pb push_back
typedef long long LL;
#define MMAX ((int)2e5+10)
vector<Node> ans;
vector<int> edge[MMAX];
int dfs(int p,int f){
	if (edge[p].size() == 1){
		return p;
	}
	int ret;
	for (int son : edge[p]){
		if (son == f)
			continue;
		ret = dfs(son, p);
		ans.push_back(Node(p, son, ret));
	}
	return ret;
}

int n;
vector<int> vi[MMAX];

int pre_dfs(int p, int f, bool root){
	if (vi[p].size() == 1){
	//	edge[p].pb(f);
	//	edge[f].pb(p);
		return p;
	}
	vector<pii> leaf;
	for (int son : vi[p]){
		if (son == f)
			continue;
		leaf.pb(mp(pre_dfs(son, p, 0),son));
	}

	if (root){
		for (int i = 0; i < leaf.size(); ++i){
			edge[leaf[i].second].push_back(p);
			edge[p].push_back(leaf[i].second);

		}
		return -1;
	}
	else{

		if (p == 7){
			int t = 0;
		}

		if (leaf.size() == 1){

			edge[p].push_back(leaf[0].second);
			edge[leaf[0].second].push_back(p);
			return leaf[0].first;
		}
		else{

			ans.push_back(Node(f, p, leaf.back().first));
			int nowf = leaf.back().second;
			int nowp = p;
			for (int i = leaf.size() - 2; i >= 0; --i){
				ans.push_back(Node(nowf, nowp, leaf[i].first));

				edge[leaf[i].first].push_back(nowf);
				edge[nowf].push_back(leaf[i].first);
				nowf = leaf[i].second;
				nowp = p;

			}
			edge[p].push_back(nowf);
			edge[nowf].push_back(p);
		}
		return p;
	}
}

void input(){
	in >> n;
	for (int i = 1; i < n; ++i){
		int a, b;
		in >> a >> b;
		vi[a].pb(b);
		vi[b].pb(a);
	}
}
bool ok[MMAX];
int roota, rootb;
int get_root(int p,int f){
	int size = 1;
	for (int son : vi[p]){
		if (son == f)
			continue;
		int tmp = get_root(son, p);
		if (tmp < n - tmp){
			ok[son] = 1;
		}

		if ( n - tmp < tmp){
			ok[p] = 1;
		}

		size += tmp;
	}

	return size;
}

int main(){

	int TEST_CASE = 1;
	//in >> TEST_CASE;
	while (TEST_CASE-- > 0){
		input();
		if (n <= 3){
			cout << 0 << endl;
			continue;
		}
		roota = rootb = -1;

		get_root(1, -1);
		vector<int> vp;
		for (int i = 1; i <= n;++i)
		if (!ok[i])
			vp.push_back(i);

		assert(vp.size() <= 2);

		roota = vp[0];
		if (vp.size() == 2){
			rootb = vp.back();
		}

		pre_dfs(roota, rootb, 1);
		if (rootb != -1){
			pre_dfs(rootb, roota, 1);
		}

		dfs(roota, -1);
		if (rootb != -1){
			dfs(rootb, -1);
		}

		printf("%d\n", ans.size());
		for (Node& p : ans){
			printf("%d %d %d\n", p.x, p.y1, p.y2);
		}

	}

	return 0;
}

#include <algorithm>
#include <array>
#include <map>
#include <functional>
#include <cstdio>
#include <vector>
#include <iterator>
#include <utility>

struct Range
{
    struct It {   int num, step; int operator*(){return num;} void operator++(){num += step;} bool operator!=(const It& other){return num != other.num;} };
    Range(int ee):b(0),e(ee){}
    Range(int bb, int ee):b(bb), e(ee){}
    It begin(){return {b, (b < e? 1: -1)};}
    It end(){return {e, 0};}
    int b, e;
};

template<typename T> inline T& UMAX(T& x, T y){if(x < y)x = y; return x;}
template<typename T> inline T& UMIN(T& x, T y){if(y < x)x = y; return x;}
template<typename T, typename... Args> struct ArithmiticPromotion { typedef decltype(T() + typename ArithmiticPromotion<Args...>::type()) type; };
template<typename T, typename U> struct ArithmiticPromotion<T, U> { typedef decltype(T() + U()) type; };
template<typename T> struct ArithmiticPromotion<T, T> { typedef T type; };
template<typename T> struct ArithmiticPromotion<T> { typedef T type; };
template<typename T, typename U> typename ArithmiticPromotion<T, U>::type MAX(T a, U b) { return a < b? b: a; }
template<typename T, typename... Args> typename ArithmiticPromotion<T, Args...>::type MAX(T a, Args... args) { return MAX(a, MAX(args...)); }
template<typename T, typename U> typename ArithmiticPromotion<T, U>::type MIN(T a, U b) { return a < b? a: b; }
template<typename T, typename... Args> typename ArithmiticPromotion<T, Args...>::type MIN(T a, Args... args) { return MIN(a, MIN(args...)); }

template<typename T> struct ScanfSpecifier{};
#define DEF(T,V) template<> struct ScanfSpecifier<T>{static constexpr const char* value = V;};
DEF(char*,"%s")DEF(int,"%d")DEF(double,"%lf")DEF(float,"%f")DEF(char,"%c")DEF(const char*,"%s")DEF(unsigned long,"%lu")DEF(unsigned int, "%u")
#ifdef _MSC_VER
DEF(long long int,"%I64d")
#else
DEF(long long int,"%lld")
#endif
#undef DEF
template<typename T> int RD(T& arg){return std::scanf(ScanfSpecifier<T>::value, &arg);}
template<int S> int RD(char (&arg)[S]){return std::scanf("%s", arg);}
int RD(char* arg){return std::scanf("%s", arg);}
template<> int RD<char>(char& arg){return std::scanf(" %c", &arg);}
template<typename T, typename... Args> int RD(T& arg1, Args&... args) {return RD(arg1) + RD(args...);}
template<typename T> T RD(){T ret; RD(ret); return ret;}
template<typename It> void RDV(It begin, It end) { while(begin != end) RD(*begin++); }
template<typename C> void RDV(C& c) {RDV(std::begin(c), std::end(c));}
template<typename T> void WT(T arg) {std::printf(ScanfSpecifier<T>::value, arg); }
template<typename T, typename U> void WT(std::pair<T, U> arg) {std::printf("("); WT(arg.first); std::printf(", "); WT(arg.second); std::printf(")");}
template<typename... Args> void WT(Args... args) { int alc = 0; int dummy[] = {((alc++? std::printf(" "): 0), WT(args), 0)...}; }

template<typename... Args> void WTL(Args... args) { WT(args...); std::printf("\n"); }
template<typename It> void WTV(It begin, It end) { int alc = 0; while(begin != end) (alc++? std::printf(" "): 0), WT(*begin++); }
template<typename C> void WTV(const C& c) {WTV(std::begin(c), std::end(c));}
template<typename It> void WTVL(It begin, It end) { WTV(begin, end); std::printf("\n"); }
template<typename C> void WTVL(const C& c) {WTVL(std::begin(c), std::end(c));}

#define _M_VARGS_NUM_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define _M_VARGS_NUM(...) _M_VARGS_NUM_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define _W1(_1) (#_1[0] == '"' || #_1[0] == '\''? WT("", _1, ""): WT('[', #_1, '=', _1, ']'))
#define _W2(_1, _2) (_W1(_1), _W1(_2))
#define _W3(_1, _2, _3) (_W1(_1), _W2(_2, _3))
#define _W4(_1, _2, _3, _4) (_W1(_1), _W3(_2, _3, _4))
#define _W5(_1, _2, _3, _4, _5) (_W1(_1), _W4(_2, _3, _4, _5))
#define _W6(_1, _2, _3, _4, _5, _6) (_W1(_1), _W5(_2, _3, _4, _5, _6))
#define _W7(_1, _2, _3, _4, _5, _6, _7) (_W1(_1), _W6(_2, _3, _4, _5, _6, _7))
#define _W8(_1, _2, _3, _4, _5, _6, _7, _8) (_W1(_1), _W7(_2, _3, _4, _5, _6, _7, _8))
#define _WW_IMPL2(num, ...) _W ## num(__VA_ARGS__)
#define _WW_IMPL(num, ...) _WW_IMPL2(num, __VA_ARGS__)
#define WW(...) (std::printf("(%03d) ", __LINE__), _WW_IMPL(_M_VARGS_NUM(__VA_ARGS__), __VA_ARGS__), WTL(""))

namespace XX
{
    template<typename... Datas>
    struct UnionFind
    {
            struct Node:public Datas...
            {
                int _parent = -1;
                void operator+=(Node& other) { int dummy[] = {(Datas::operator+=(other), 0)...}; }
            };
            UnionFind(int size = 0) :_data(size, Node()) {}

            void resize(int size)
            {
                _data.resize(size, Node());
            }

            int size()
            {
                return _data.size();
            }

            Node& operator[](int idx) { return _data[(*this)(idx)]; }

            int operator()(int n)
            {
                if(_data[n]._parent < 0)
                    return n;
                else
                    return _data[n]._parent = (*this)(_data[n]._parent);
            }

            bool operator()(int a, int b)
            {
                int pa = (*this)(a), pb = (*this)(b);
                if(pa == pb)
                    return false;
                else
                {
                    if(_data[pa]._parent == _data[pb]._parent)
                        _data[pa]._parent--;
                    else if(_data[pa]._parent > _data[pb]._parent)
                        std::swap(pa, pb);

                    _data[pa] += _data[pb];
                    _data[pb]._parent = pa;
                    return true;
                }
            }

            std::vector<Node> _data;
    };
}

//alias
//RD[L],RDV[L],WT[L],WTV[L] for i/o
using RG = Range;
//template
#include <vector>
#include <string>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <cstdlib>
#include <algorithm>
#include <functional>
using namespace std;

//alias
//for union/find
template<typename... Datas>
using UF = XX::UnionFind<Datas...>;
typedef long long int ll;
const int SIZE = 200009;

vector<int> adj[SIZE];
int N;

int size[SIZE];
struct S
{
    int size;
    int u, v;

    bool operator<(S rhs)const
    {
        return size < rhs.size;
    }
};

vector<S> cad;
void dfs(int u, int p)
{
    size[u] = 1;
    for(int to: adj[u])
        if(to != p)
        {
            dfs(to, u);
            size[u] += size[to];
            if(size[to] < N - size[to])
                cad.push_back({size[to] + 1, u, to});
            if(N - size[to] < size[to])
                cad.push_back({N - size[to] + 1, to, u});
        }
}

struct Data
{
    int cent;
    void operator+=(Data& rhs){}
};

int main()
{
    RD(N);
    for(int i: RG(N - 1))
    {
        int u, v;
        RD(u, v);
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    UF<Data> uf(N + 1);
    for(int i: RG(1, N + 1))
        uf[i].cent = i;
    dfs(1, 0);
    sort(cad.begin(), cad.end());

    vector<S> ans;
    for(auto c: cad)
    {
        int cent = uf[c.v].cent;

        ans.push_back({c.u, c.v, cent});
        uf(c.u, c.v);
        uf[c.u].cent = cent;
    }

    WTL(ans.size());
    for(int i: RG(ans.size()))
        WTL(ans[i].size, ans[i].u, ans[i].v);

}

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cmath>
#include <cstring>
#include <ctime>
#include <unordered_map>
#include <iomanip>
#include <complex>
using namespace std;

#define fi first
#define se second
#define pb push_back
#define all(v) (v).begin(),(v).end()

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int,int> pii;

struct oper{
    int x,y,ny;
    oper(int x=0, int y=0, int ny=0) : x(x),y(y),ny(ny) {}
};

int N,sz[200010],t[200010]; vi g[200010];
vi narr; vector<oper> ans;

void dfs_sz(int nod, int f){
    sz[nod]=1;

    for (int nxt : g[nod]){
        if (nxt==f) continue;

        dfs_sz(nxt,nod);
        sz[nod]+=sz[nxt];
    }
}

void dfs_flat(int nod, int f){
    t[nod] = f;
    for (int nxt : g[nod]){
        if (nxt==f) continue;
        dfs_flat(nxt,nod);
        narr.pb(nxt);
    }
}

void flat_subtree(int nod, int f){
    narr.clear();
    dfs_flat(nod,f);

    int x=f,y=nod;
    for (int nxt : narr){
        ans.pb(oper(x,y,nxt));
        x=nxt,y=t[nxt];
    }
}

void star(vi &narr, int f){
    narr.insert(narr.begin(),f);
    int p=narr.size()-4;
    int ny=narr[narr.size()-2];
    while (p>=0){
        ans.pb(oper(narr[p],narr[p+1],ny));
        p--;
    }
}

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

    int i,x,y;
    for (i=1; i<N; i++){
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs_sz(1,0);

    int nod = 1;
    bool ok=0;
    while (!ok){
        ok=1;
        for (int nxt : g[nod])
            if (2*sz[nxt]>N){
                sz[nod]-=sz[nxt];
                sz[nxt]+=sz[nod];
                nod=nxt;
                ok=0;
                break;
            }
    }

    for (int nxt : g[nod]){
        if (2*sz[nxt]==N){
            for (int nnxt : g[nxt]){
                flat_subtree(nnxt,nxt);
                narr.pb(nnxt);
                star(narr,nxt);
            }
        }
        else {
            flat_subtree(nxt,nod);
            narr.pb(nxt);
            star(narr,nod);
        }
    }

    cout << ans.size() << "\n";
    for (oper o : ans)
        cout << o.x << " " << o.y << " " << o.ny << "\n";

    return 0;
}

#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
int N, M;
vector <int> G[200005];
int Sz[200005], Size[200005];
int sum, cnt;
bool Blocked[200005];
struct Solution{
int x, y, y2;
} S[200005];
bool first;
void Read()
{
    scanf("%d", &N);
    for(int i = 2; i <= N; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
}

void DFS(int node, int father)
{
    Sz[node] = 1;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        DFS(neighb, node);
        Sz[node] += Sz[neighb];
    }
}

int findCentroid(int node, int father, int size)
{
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        if(Sz[neighb] > size / 2)
            return findCentroid(neighb, node, size);
    }
    return node;
}

int centroidDecompose(int root)
{
    DFS(root, 0);
    int center = findCentroid(root, 0, Sz[root]);
    Blocked[center] = 1;
    int sz = Sz[root];
    bool ok = 0;
    if(first == 0)
    {
        for(int i = 1; i <= N; i++)
        Size[i] = Sz[i];
        first = 1;
        ok = 1;
    }

    int node = center;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        int from = center;
        if(Blocked[neighb] == 1)
            continue;
        if(ok == 1 && Size[neighb] == N - Size[neighb])
            from = neighb;
        int n = centroidDecompose(neighb);
        if(n == neighb || n == from)
            continue;
        ++cnt;
        S[cnt].x = center;
        S[cnt].y = neighb;
        S[cnt].y2 = n;
    }
    return center;
}
int main()
{
    Read();
    int root = 1;
    DFS(root, 0);
    bool ok = 0;
    int center = findCentroid(root, 0, Sz[root]);
    for(int i = 0; i < G[center].size(); i++)
    {
        int neighb = G[center][i];
        if(Sz[neighb] == N - Sz[neighb])
        {
            for(auto it = G[neighb].begin(); it != G[neighb].end(); it = next(it))
                if(*it == center)
                    G[neighb].erase(it);
            swap(G[center][i], G[center][G[center].size() - 1]);
            G[center].pop_back();
            ok = 1;
            centroidDecompose(center);
            centroidDecompose(neighb);
            break;
        }
    }
    if(ok == 0)
        centroidDecompose(1);
    printf("%d\n", cnt);
    for(int i = cnt; i >= 1; i--)
    {
        printf("%d %d %d\n", S[i].x, S[i].y, S[i].y2);
    }
    return 0;
}

#include <bits/stdc++.h>

using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ll long long
const int N = 1e6+5;
int size[N],n,G,G_size=1e6+5;
vector<int>g[N];
int dfs(int u,int fa)
{
	size[u]=1;
	for(auto &v:g[u]){if(v==fa)continue;size[u]+=dfs(v,u);}
	return size[u];
}
void dfs1(int u,int fa)
{
	int ma=n-size[u];
	for(auto &v:g[u]){if(v==fa)continue;dfs1(v,u);}
	for(auto &v:g[u]){if(v==fa)continue;ma=max(ma,size[v]);}
	if(ma<G_size){G_size=ma;G=u;}
}
vector<vector<int> >ans;
pair<int,int> dfs2(int u,int fa)
{
	vector<pair<int,int> >tmp;
	for(auto &v:g[u]){if(v==fa)continue;pair<int,int> s=dfs2(v,u);tmp.pb(s);if(size[v]*2<n&&v)ans.pb({u,v,s.fi});}
	int G1=u,ma=0,maa=0;vector<int>dp;
	for(auto &t:tmp){ma=max(ma,t.se+1);dp.pb(0);}
	for(int i=0;i<(int)tmp.size();i++)dp[i]=max(i?dp[i-1]:0,tmp[i].se);
	for(int i=(int)tmp.size()-1;i>=0;i--){
		int tmp_ma=max(i?dp[i-1]:0,maa);
		int tmp_ma1=max(tmp_ma+1,tmp[i].se);
		if(tmp_ma1<ma){ma=tmp_ma1;G1=tmp[i].fi;}
		maa=max(maa,tmp[i].se);
	}
	return {G1,ma};
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].pb(v);g[v].pb(u);}
	dfs(1,-1);dfs1(1,-1);dfs(G,-1);dfs2(G,-1);
	printf("%d\n",(int)ans.size());
	for(auto &t:ans)printf("%d %d %d\n",t[0],t[1],t[2] );
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define sqr(x) ((x)*(x))
#define par make_pair
#define pb push_back
#define fi first
#define se second
#define endl '\n'
template<class X, class Y> void amax(X& x, const Y& y){if(x < y) x = y;}
template<class X, class Y> void amin(X& x, const Y& y){if(x > y) x = y;}
typedef vector<int> vi; typedef pair<int, int> ii; typedef long long ll; typedef long double ld;
const int INF = 1e9 + 10; const ll INFL = 1e18 + 10;
const int MAX = 2e5 + 10;

struct op{
    int x, y, z;
};

int n, moment, trsz;
vi es[MAX];
vector<op> res;
bool mark[MAX];
ii sz[MAX];

void add_op(const op &x){
    if(x.x < 1 || x.y < 1 || x.z < 1 || x.y == x.z) return;
    res.pb(x);
}

void add(ii &p, int value){
    if(p.se < moment) p = par(value, moment);
    else p.fi += value;
}

ii dfs_centroid(int u, int p){
    for(auto v : es[u])
    if(!mark[v] && v != p){
        if(sz[v].fi > trsz/2) return dfs_centroid(v, u);
        if(sz[v].fi == (trsz + 1)/2) return par(u, v);
    }
    return par(u, 0);
}

void dfs_size(int u, int p){
    add(sz[u], 1);
    for(auto v : es[u]) if(!mark[v] && v != p){
        dfs_size(v, u);
        add(sz[u], sz[v].fi);
    }
}

void find_centroid(int u, int pc){
    moment++;
    dfs_size(u, 0);
    trsz = sz[u].fi;
    ii x = dfs_centroid(u, 0);
    mark[x.fi] = mark[x.se] = true;
    add_op(op{pc, u, x.fi});
    for(auto v : es[x.fi]) if(!mark[v]) find_centroid(v, x.fi);
    for(auto v : es[x.se]) if(!mark[v]) find_centroid(v, 0);
}

void process(){
    cin >> n;
    for(int i = 1; i < n; i++){
        int u, v; cin >> u >> v;
        es[u].pb(v); es[v].pb(u);
    }

    find_centroid(1, 0);
    cout << res.size() << endl;
    for(auto v : res) cout << v.x << " " << v.y << " " << v.z << endl;
}

int main(){
    ios_base::sync_with_stdio(false);
    //cin.tie(NULL);
    //freopen("c.in", "r", stdin);
    process();
}

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

const int N = 2 * 1000 * 100 + 10;
int n, par[N], mx[N], sz[N], c1, c2;
vector<int> adj[N], vec;
vector<pair<int, pair<int, int>>> ans;

void dfs(int root, int par = -1) {
	mx[root] = sz[root] = 0;
	for (auto u: adj[root])
		if (u ^ par) {
			dfs(u, root);
			sz[root] += sz[u];
			if (sz[u] > sz[mx[root]])
				mx[root] = u;
		}
	sz[root]++;
}

int centroid(int v) {
	dfs(v);
	while (sz[mx[v]] * 2 > n)
		v = mx[v];
	return v;
}

void dfs2(int root, int p) {
	par[root] = p;
	vec.push_back(root);
	for (auto u: adj[root])
		if (u ^ p)
			dfs2(u, root);
}

void do_shit(int c) {
	if (c <= 0)
		return;
	for (auto u: adj[c])
		if (u != c1 && u != c2) {
			vec.clear();
			dfs2(u, c);
			int root = u, tar = u;
			for (auto x: vec) {
				if (x == tar)
					continue;
				if (root != x)
					ans.push_back({c, {root, x}});
				root = x;
				ans.push_back({x, {par[x], tar}});
			}
			if (root != tar)
				ans.push_back({c, {root, tar}});
		}
}

int main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 1, v, u; i < n; i++) {
		cin >> v >> u;
		adj[v].push_back(u);
		adj[u].push_back(v);
	}
	c1 = centroid(1), c2 = -1;
	if (n % 2 == 0)
		c2 = mx[c1];
	do_shit(c1), do_shit(c2);
	cout << (int)(ans.size()) << '\n';
	for (auto it: ans)
		cout << it.first << ' ' << it.second.first << ' ' << it.second.second << '\n';
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define pb push_back
#define mp make_pair

int n;
set<int> g[200010];
deque<pii> q[200010];
char c[200010];
set<int> centers;
struct tup{
    int x, y, yy, p;
    tup(int x, int y, int yy): x(x), y(y), yy(yy) {}
};
vector<tup> ans;
queue<tup> tmp;
vector<int> cur;
int d[200010];

void dfs1(int v, int p){
    for(auto to: g[v]){
        if(to != p){
            dfs1(to, v);
            d[v] += d[to];
        }
    }
    d[v]++;
}

void find_centers(){
    dfs1(0, 0);
    for(int i = 0; i < n; i++){
        bool canCenter = true;
        for(auto to: g[i]){
            int cursz;
            if(d[to] < d[i]) cursz = d[to];
            else cursz = n - d[i];
            if(cursz > n / 2) canCenter = false;
        }
        if(canCenter){
            c[i] = true;
            centers.insert(i);
        }
    }
}

void freeQ(){
    while(!tmp.empty()){
        tup u = tmp.front();
        tmp.pop();
        g[u.x].erase(u.y);
        g[u.y].erase(u.x);
        g[u.x].insert(u.yy);
        g[u.yy].insert(u.x);
        cout << u.x + 1 << ' ' << u.y + 1 << ' ' << u.yy + 1 << endl;
    }
}

int go(int v, int p){
    for(auto to: g[v]){
        if(to != p) return go(to, v);
    }
    return v;
}

pii solve(int v, int p){
    vector<int> t;
    for(auto to: g[v]) if(to != p) t.pb(to);
    int lo, hi;
    if(t.empty()) lo = hi = v;
    for(auto to: t){
        q[v].push_back(solve(to, v));
        //cout << v + 1 << ' ' << to + 1 << ' ' << q[v].back().first + 1 << ' ' << q[v].back().second + 1 << endl;
    }
    if(!q[v].empty()){
        if(q[v].size() != 1) lo = q[v].front().first;
        else lo = v;
        hi = q[v].back().first;
    }
    while(q[v].size() > 1){
        ans.pb(tup(p, v, q[v].front().first));
        tmp.push(tup(p, v, q[v].front().first));
        p = q[v].front().second;
        q[v].pop_front();
    }
    freeQ();
    return mp(hi, lo);
}

void solve2(int v, int p){
    cur.pb(v);
    for(auto to: g[v]){
        if(to != p) solve2(to, v);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n;
    for(int i = 0; i < n - 1; i++){
        int from, to;
        cin >> from >> to;
        g[from - 1].insert(to - 1);
        g[to - 1].insert(from - 1);
    }
    find_centers();
    for(auto u: centers){
        vector<int> t;
        for(auto v: g[u]) if(!c[v]) t.pb(v);
        for(auto v: t){
            solve(v, u);
            freeQ();
        }
    }
    /*cout << endl;
    for(int i = 0; i < n; i++){
        for(auto to: g[i]){
            if(i < to) cout << i + 1 << ' ' << to + 1 << endl;
        }
    }*/
    for(auto u: centers){
        for(auto to: g[u]){
            if(c[to]) continue;
            cur.clear();
            cur.pb(u);
            solve2(to, u);
            cur.pop_back();
            int last = cur.back();
            cur.pop_back();
            for(int i = (int)cur.size() - 1; i >= 1; i--){
                ans.pb(tup(cur[i - 1], cur[i], last));
            }
        }
    }
    cout << ans.size() << endl;
    for(auto u: ans){
        cout << u.x + 1 << ' ' << u.y + 1 << ' ' << u.yy + 1 << endl;
    }
    return 0;
}

#include <cstdio>
using namespace std;
struct node
{
	int to;
	node *next;
};
struct rec
{
	int a,b,c;
};
int i,j,m,n,size[200005],cen,cnt,ver[200005],ind[200005],now[200005],cntans,dep[200005];
node *nd[200005];
rec ans[200005];
bool centroid[200005];
void addd(int u,int v){
	node *p=new node();
	p->to=v;
	p->next=nd[u];
	nd[u]=p;
}
void dfs0(int u,int pre){
	node *p;
	p=nd[u];
	while(p){
		if (p->to!=pre){
			dep[p->to]=dep[u]+1;
			dfs0(p->to,u);
		}
		p=p->next;
	}
}
void dfs2(int u,int pre){
	node *p;
	node *pp;
	p=nd[u];
	if ((u!=cen)&&(u!=ver[cnt])){
		ind[u]=cnt;
		cntans++;
		ans[cntans].a=cen;
		ans[cntans].b=now[cnt];
		ans[cntans].c=u;
		now[cnt]=u;
		pp=nd[u];
		while(pp){
			if (pp->to!=cen){
				if (dep[u]>dep[pp->to]){
					cntans++;
					ans[cntans].a=u;
					ans[cntans].b=pp->to;
					ans[cntans].c=ver[cnt];
				}
			}
			pp=pp->next;
		}
	}
	while(p){
		if (p->to!=pre){
			if (u==cen){
				cnt++;
				ver[cnt]=p->to;
				now[cnt]=p->to;
			}
			//dep[p->to]=dep[u]+1;
			dfs2(p->to,u);

		}
		p=p->next;
	}
}
void dfs(int u,int pre){
	node *p;
	p=nd[u];
	size[u]=1;
	while(p){
		if (p->to!=pre){
			dfs(p->to,u);
			size[u]+=size[p->to];
			if (size[p->to]*2>n) centroid[u]=false;
		}
		p=p->next;
	}
	if (2*(n-size[u])>n) centroid[u]=false;
	if (centroid[u]) cen=u;
}
int main(){
	cnt=cntans=0;
	scanf("%d",&n);
	int x,y;
	for(i=1;i<=n-1;i++){
		scanf("%d%d",&x,&y);
		addd(x,y);
		addd(y,x);
	}
	for(i=1;i<=n;i++) centroid[i]=true;
	dfs(1,-1);
	dep[cen]=0;
	dfs0(cen,-1);
	dfs2(cen,-1);
	for(i=1;i<=cnt;i++){
		cntans++;
		ans[cntans].a=cen;
		ans[cntans].b=now[i];
		ans[cntans].c=ver[i];
	}
	//printf("%d\n", );
	printf("%d\n",cntans);
	for(i=1;i<=cntans;i++){
		printf("%d %d %d\n",ans[i].a,ans[i].b,ans[i].c);
	}
	return 0;
}

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <sstream>
#include <string>
#include <map>
#include <set>
#include <stdlib.h>
#include <cmath>
#include <math.h>
#include <fstream>
#include <bitset>
#include <queue>
#include <ctime>
#define int long long
using namespace std;
int INF = 1e18;
int maximum, n, ai, bi;
struct Vertex{int l; int r; int pr; int sz; int value; bool p;};
vector<Vertex> decart;
vector<vector<int> > data, ne, ans;
vector<pair<int, int> > edges;
vector<int> h, bases;
vector<bool> orient;
pair<int, int> SP = make_pair(-1, -1);
void update(int vertex){
    if (vertex == -1) return;
    int sz = 1;
    if (decart[vertex].l != -1){
        sz += decart[decart[vertex].l].sz;
    }
    if (decart[vertex].r != -1){
        sz += decart[decart[vertex].r].sz;
    }
    decart[vertex].sz = sz;
}
void push(int vertex){
    if (vertex == -1) return;
    if (!decart[vertex].p) return;
    decart[vertex].p = false;
    swap(decart[vertex].l, decart[vertex].r);
    if (decart[vertex].l != -1){
		decart[decart[vertex].l].p ^= 1;
    }
    if (decart[vertex].r != -1){
		decart[decart[vertex].r].p ^= 1;
    }
}
pair<int, int> split(int father, int number){
    if (father == -1) return SP;
    push(father);
    int l = 1;
    if (decart[father].l != -1){
        l += decart[decart[father].l].sz;
    }
    if (l <= number){
        pair<int, int> p = split(decart[father].r, number - l);
        decart[father].r = p.first;
        p.first = father;
        update(father);
        return p;
    }
    pair<int, int> p = split(decart[father].l, number);
    decart[father].l = p.second;
    p.second = father;
    update(father);
    return p;
}
int merg(int first, int second){
    push(first);
    push(second);
    if (first == -1) return second;
    if (second == -1) return first;
    if (decart[first].pr >= decart[second].pr){
        int v = merg(decart[first].r, second);
        decart[first].r = v;
        update(first);
        return first;
    }
    int v = merg(first, decart[second].l);
    decart[second].l = v;
    update(second);
    return second;
}
int dfs(int vertex, int last){
	int g = 1;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (last == to) continue;
        int num_e = ne[vertex][i];
        if (edges[num_e].first != vertex) orient[num_e] = false;
		g += dfs(to, vertex);
	}
	h[vertex] = g;
	return g;
}
int get_left(int vertex){
	push(vertex);
	if (decart[vertex].l == -1) return decart[vertex].value;
	return get_left(decart[vertex].l);
}
void form(int vertex, int e, int last){
	Vertex v = {-1, -1, rand(), 1, e, false};
	decart.push_back(v);
	int num = decart.size() - 1;
	int lastv;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (last == to) continue;
		lastv = i;
	}
    for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (last == to) continue;
		form(to, ne[vertex][i], vertex);
		if (i == lastv){
			num = merg(num, bases[to]);
			continue;
		}
		int b = bases[to];
		decart[b].p ^= 1;
        int ed = get_left(b);
        int so;
        if (orient[ed]) so = edges[ed].second;
        else so = edges[ed].first;
        vector<int> help;
        help.push_back(last);
        help.push_back(vertex);
        help.push_back(so);
        ans.push_back(help);
        if (edges[e].first == vertex){
			edges[e].first = so;
		}
		else edges[e].second = so;
		num = merg(num, b);
    }
    bases[vertex] = num;
}
void solve(int vertex, int sec){
	vector<int> sv;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		if (to == sec) continue;
		sv.push_back(to);
        form(data[vertex][i], ne[vertex][i], vertex);
	}
	if (sec != -1){
	for (int i=0; i < data[sec].size(); i++){
		int to = data[sec][i];
		if (to == vertex) continue;
		sv.push_back(to);
        form(data[sec][i], ne[sec][i], sec);
	}
	}
	for (int i=0; i < sv.size(); i++){
		int to = sv[i];
        int b = bases[to];
        int sz = decart[b].sz;
        if (sz <= 2) continue;
        pair<int, int> p = split(b, sz-1);
        pair<int, int> p1 = split(p.first, sz-2);
        int ov, ev;
        int N = decart[p.second].value;
        int V = decart[p1.second].value;
        if ((edges[N].first == edges[V].second) || (edges[N].second == edges[V].second)){
			ov = edges[V].second;
			ev = edges[V].first;
        }
        if ((edges[N].first == edges[V].first) || (edges[N].second == edges[V].first)){
			ev = edges[V].second;
			ov = edges[V].first;
        }
        b = p1.first;
        while (b != -1){
            pair<int, int> p = split(b, decart[b].sz - 1);
			b = p.first;
			int W = decart[p.second].value;
			if (edges[W].first == ev){
                vector<int> help;
                help.push_back(edges[W].second);
                help.push_back(edges[W].first);
                help.push_back(ov);
                ans.push_back(help);
                ev = edges[W].second;
			}
			else{
				vector<int> help;
                help.push_back(edges[W].first);
                help.push_back(edges[W].second);
                help.push_back(ov);
                ans.push_back(help);
                ev = edges[W].first;
			}
        }
	}
}
void get_centroid(int vertex){
	maximum = 0;
	int wh;
	for (int i=0; i < data[vertex].size(); i++){
		int to = data[vertex][i];
		int res = dfs(to, vertex);
		if (res > maximum){
			maximum = res;
			wh = to;
		}
	}
	int ll = vertex;
	while (maximum*2 > n){
		int mm = 0, vv;
		for (int i=0; i < data[wh].size(); i++){
			int to = data[wh][i];
			if (to == ll) continue;
			if (h[to] > mm){
				mm = h[to];
				vv = to;
			}
		}
        maximum = mm;
        ll = wh;
        wh = vv;
	}
	dfs(ll, -1);
	int se = -1;
	for (int i=0; i < data[ll].size(); i++){
		int to = data[ll][i];
        if (2 * h[to] >= n){
			se = to;
        }
	}
    solve(ll, se);
}
int32_t main(){
    cin >> n;
    for (int i=0; i < n; i++){
		vector<int> help, hh;
		h.push_back(0);
		ne.push_back(hh);
		bases.push_back(-1);
		orient.push_back(true);
		data.push_back(help);
    }
    for (int i=0; i < n-1; i++){
		cin >> ai >> bi;
		data[ai-1].push_back(bi-1);
		data[bi-1].push_back(ai-1);
		ne[ai-1].push_back(i);
		ne[bi-1].push_back(i);
		edges.push_back(make_pair(ai-1, bi-1));
    }
    get_centroid(0);
    cout << ans.size() << endl;
    for (int i=0; i < ans.size(); i++){
		cout << ans[i][0] + 1 << " " << ans[i][1] + 1 << " " << ans[i][2] + 1 << endl;
    }
	return 0;
}

#include <bits/stdc++.h>

#define FOR(i,b,e) for(int i=(b); i <= (e); ++i)
#define FORD(i,b,e) for(int i=(b); i >= (e); --i)
#define REP(i,n) for(int i=0; i < (n); ++i)
#define SIZE(c) (int) (c).size()
#define ALL(c) (c).begin(), (c).end()
#define PB push_back
#define MP make_pair
#define ST first
#define ND second
#define FWD(i,a,b) for (int i=(a); i<(b); ++i)
#define BCK(i,a,b) for (int i=(a); i>(b); --i)
#define PI 3.14159265358979311600
#define pb push_back
#define mp make_pair
#define st first
#define nd second

using namespace std;

typedef long long ll;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;

typedef vector < int > VI;
typedef vector<ll> VL;

typedef long double K;

const int N = 200005;

int n, taken[N], sz[N];
vector<int> g[N];
set<int> s[N];
vector<int> centroids;
vector<tuple<int,int,int>> result;

void dfs(int v, int pr = -1) {
	sz[v] = 1;
	int mx = 0;
	for (auto& to : g[v]) if (to != pr) {
		dfs(to, v);
		sz[v] += sz[to];
		mx = max(mx, sz[to]);
	}
	mx = max(mx, n - sz[v]);
	if (2*mx <= n) {
		centroids.push_back(v);
		taken[v] = 1;
	}
}

void output(int a, int b, int c, bool change = true) {
	result.emplace_back(a+1, b+1, c+1);
	if (change) {
		s[a].erase(b);
		s[b].erase(a);
		s[a].insert(c);
		s[c].insert(a);
	}
}

pair<int,int> bamboo(int v, int pr) {
	vector<pair<int,int>> all;
	for (auto& to : g[v]) if (to != pr) {
		all.push_back(bamboo(to, v));
	}
	if (all.empty()) return {v, v};
	for (int i = 0; i < SIZE(all) - 1; ++i) {
		output(pr, v, all[i].second);
		pr = all[i].first;
	}
	return {all[0].second, all.back().second};
}

int solve(int v, int pr) {
	sz[v] = 1;
	int here;
	for (auto& to : s[v]) if (to != pr) {
		here = solve(to, v);
		sz[v] += sz[to];
	}
	if (sz[v] <= 2) return v;
	output(pr, v, here, false);
	return here;
}

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

	cin >> n;

	REP(i, n - 1) {
		int x, y;
		cin >> x >> y;
		--x; --y;
		g[x].push_back(y);
		g[y].push_back(x);
		s[x].insert(y);
		s[y].insert(x);
	}

	dfs(0);

	for (auto& v : centroids) {
		for (auto& ver : g[v]) {
			if (taken[ver]) continue;
			bamboo(ver, v);
		}
		for (auto& ver : s[v]) {
			solve(ver, v);
		}
	}

	cout << SIZE(result) << '\n';

	for (auto& item : result) {
		int a, b, c;
		tie(a, b, c) = item;
		cout << a << ' ' << b << ' ' << c << '\n';
	}

	return 0;
}

#include <bits/stdc++.h>

using namespace std;

#define mp make_pair
#define pb push_back
#define makeunique(x) sort(all(x)), (x).resize(unique(x) - (x).begin())
#define re return
#define fi first
#define se second
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define sqrt(x) sqrt(abs(x))
#define y0 y3487465
#define y1 y8687969
#define j0 j5743892
#define j1 j542893

typedef vector<int> vi;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double D;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef vector<vi> vvi;

template<class T> T abs(T x) { re x > 0 ? x : -x; }
template<class T> T gcd(T a, T b) { re a ? gcd (b % a, a) : b; }
template<class T> T sqr(T a) { re a * a; }
template<class T> T sgn(T a) { re a > 0 ? 1 : (a < 0 ? -1 : 0); }

#define filename ""

int n;
int m;

const int N = 1e5 + 10;
int sz[N];
vi v[N];

int comp_size(int x, int p)
{
	for (auto y : v[x]) {
		if (y == p) continue;
		sz[x] += comp_size(y, x);
	}
	re ++sz[x];
}

vi find_center(int x)
{
	bool ok;
	int cur = x, p = cur;
	do {
		ok = false;
		for (auto y : v[cur]) {
			if (y == p) continue;
			if (2 * sz[y] >= n) {
				p = cur;
				cur = y;
				ok = true;
				break;
			}
		}
	} while (ok);
	vi res;
	res.pb (cur);
	if (2 * (n - sz[p] + 1) >= n) res.pb (p);
	re res;
}

int last = -1;
vvi cert;

void go (int x, int p, int gen, int to)
{
	for (auto y : v[x]) {
		if (y == p) continue;
		cert.pb(vi{gen, last, y}); last = y;
		cert.pb(vi{y, x, to});
		go(y, x, gen, to);
	}
}

void calc(int x, int p)
{
	for (auto y : v[x]) {
		if (y == p) continue;
		last = y;
		go(y, x, x, y);
		cert.pb (vi{x, last, y});
	}
}

int main () {
//	freopen (filename".in", "r", stdin);
//	freopen (filename".out", "w", stdout);
	scanf ("%d", &n);
	for (int i = 0; i < n - 1; i++) {
		int x, y;
		scanf ("%d%d", &x, &y); x--; y--;
		v[x].pb (y);
		v[y].pb (x);
	}
	comp_size(0, 0);
	vi c = find_center(0);

	if (sz (c) == 1) calc(c[0], -1);
	else {
		calc(c[0], c[1]);
		calc(c[1], c[0]);
	}
	printf ("%d\n", sz(cert));
	for (auto y : cert) {
		for (auto z : y) printf ("%d ", z + 1);
		puts("");
	}

	return 0;
}

#ifndef __clang__
#pragma GCC optimize "-O3"
#pragma GCC target "tune=native"
#endif
#ifdef ONLINE_JUDGE
#define NDEBUG 1
#endif
#include <stdio.h>
#include <bits/stdc++.h>

#define DESTRUCT2(p, a, b)                      \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);

#define DESTRUCT3(p, a, b, c)                   \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);                           \
  auto c = get<2>(p);

#define DESTRUCT4(p, a, b, c, d)                \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);                           \
  auto c = get<2>(p);                           \
  auto d = get<3>(p);

#define FOR(i, n)     for(lli i = 0; i < (lli)(n); ++i)
#define FORU(i, j, k) for(lli i = (j); i <= (lli)(k); ++i)
#define FORD(i, j, k) for(lli i = (j); i >= (lli)(k); --i)

#define SQ(x) ((x)*(x))

#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define eb emplace_back

using namespace std;

template<typename... As>
struct tpl : public std::tuple<As...> {
  using std::tuple<As...>::tuple;
  tpl(std::tuple<As...> const& b) { std::tuple<As...>::operator=(b); }

  template<typename T = tuple<As...> >
  typename tuple_element<0, T>::type const&
  x() const { return get<0>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<0, T>::type&
  x() { return get<0>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<1, T>::type const&
  y() const { return get<1>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<1, T>::type&
  y() { return get<1>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<2, T>::type const&
  z() const { return get<2>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<2, T>::type&
  z() { return get<2>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<3, T>::type const&
  w() const { return get<3>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<3, T>::type&
  w() { return get<3>(*this); }
};

using lli   = long long int;
using llu   = long long unsigned;

using pii   = tpl<lli, lli>;
using piii  = tpl<lli, lli, lli>;
using piiii = tpl<lli, lli, lli, lli>;
using vi    = vector<lli>;
using vii   = vector<pii>;
using viii  = vector<piii>;
using vvi   = vector<vi>;
using vvii  = vector<vii>;
using vviii = vector<viii>;

template<class T>
using min_queue = priority_queue<T, vector<T>, greater<T> >;
template<class T>
using max_queue = priority_queue<T>;

template<size_t... I>
struct my_index_sequence {
  using type = my_index_sequence;
  static constexpr array<size_t, sizeof...(I)> value = { {I...} };
};

namespace my_index_sequence_detail {
  template<typename I, typename J> struct concat;
  template<size_t... I, size_t... J>
  struct concat<my_index_sequence<I...>, my_index_sequence<J...> > :
    my_index_sequence<I..., (sizeof...(I)+J)...> { };
  template<size_t N> struct make_index_sequence :
    concat<typename make_index_sequence<N/2>::type, typename make_index_sequence<N-N/2>::type>::type { };
  template <> struct make_index_sequence<0> : my_index_sequence<>{};
  template <> struct make_index_sequence<1> : my_index_sequence<0>{};
}

template<class... A>
using my_index_sequence_for = typename my_index_sequence_detail::make_index_sequence<sizeof...(A)>::type;

template<class T, size_t... I>
void print_tuple(ostream& s, T const& a, my_index_sequence<I...>){
  using swallow = int[];
  (void)swallow{0, (void(s << (I == 0? "" : ", ") << get<I>(a)), 0)...};
}

template<class T>
ostream& print_collection(ostream& s, T const& a);
template<class... A>
ostream& operator<<(ostream& s, tpl<A...> const& a);
template<class... A>
ostream& operator<<(ostream& s, tuple<A...> const& a);
template<class A, class B>
ostream& operator<<(ostream& s, pair<A, B> const& a);

template<class T, size_t I>
ostream& operator<<(ostream& s, array<T, I> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, vector<T> const& a) { return print_collection(s, a); }
template<class T, class U>
ostream& operator<<(ostream& s, multimap<T, U> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, multiset<T> const& a) { return print_collection(s, a); }
template<class T, class U>
ostream& operator<<(ostream& s, map<T, U> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, set<T> const& a) { return print_collection(s, a); }

template<class T>
ostream& print_collection(ostream& s, T const& a){
  s << '[';
  for(auto it = begin(a); it != end(a); ++it){
    s << *it;
    if(it != prev(end(a))) s << " ";
  }
  return s << ']';
}

template<class... A>
ostream& operator<<(ostream& s, tpl<A...> const& a){
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}

template<class... A>
ostream& operator<<(ostream& s, tuple<A...> const& a){
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}

template<class A, class B>
ostream& operator<<(ostream& s, pair<A, B> const& a){
  return s << "(" << get<0>(a) << ", " << get<1>(a) << ")";
}

namespace std {
  namespace {
    template <class T>
    inline void hash_combine(size_t& seed, T const& v) {
      seed ^= hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
    }
    template <class Tuple, size_t Index = tuple_size<Tuple>::value - 1>
    struct HashValueImpl {
      static void apply(size_t& seed, Tuple const& tuple) {
        HashValueImpl<Tuple, Index-1>::apply(seed, tuple);
        hash_combine(seed, get<Index>(tuple));
      }
    };
    template <class Tuple>
    struct HashValueImpl<Tuple, 0> {
      static void apply(size_t& seed, Tuple const& tuple) {
        hash_combine(seed, get<0>(tuple));
      }
    };
  }
  template <typename ... TT>
  struct hash<tuple<TT...>> {
    size_t operator()(tuple<TT...> const& tt) const {
      size_t seed = 0;
      HashValueImpl<tuple<TT...> >::apply(seed, tt);
      return seed;
    }
  };
  template <typename ... TT>
  struct hash<tpl<TT...>> {
    size_t operator()(tpl<TT...> const& tt) const {
      size_t seed = 0;
      HashValueImpl<tuple<TT...> >::apply(seed, tt);
      return seed;
    }
  };
}

//------------------------------------------------------------------------------

void test(lli n, vii ES, vector<tpl<lli,lli,lli>> ans) {
  vector<set<lli>> G(n);
  for(auto const &p :ES) {
    lli u,v; tie(u,v) = p;
    G[u].insert(v);
    G[v].insert(u);
  }
  for(auto const& p : ans) {
    lli x,y,z; tie(x,y,z) = p;
    assert(G[x].count(y));
    assert(G[y].count(x));
    function<lli(lli,lli)> dfs = [&](lli i, lli p) {
      lli sz=1;
      for(lli j : G[i]) if(j!=p) {
          sz+=dfs(j,i);
        }
      return sz;
    };
    lli szx = dfs(x,y);
    lli szy = dfs(y,x);
    cerr << p << " " << mt(szx,szy) << " " << n << endl;
    assert(szx>szy);
    G[x].erase(y); G[y].erase(x);
    assert(!G[z].count(x));
    assert(!G[x].count(z));
    G[x].insert(z); G[z].insert(x);
  }
  lli r=0;
  function<void(lli,lli,lli,lli)> dfs = [&](lli i0, lli i, lli p, lli d) {
    r += d*d;
    for(lli j : G[i]) if(j!=p) {
        dfs(i0,j,i,d+1);
      }
  };
  FOR(i,n) dfs(i,i,-1,0);
  cerr << r << endl;
}

int main(){
  ios::sync_with_stdio(0); cin.tie(0);
  lli n; cin>>n;
  vvi G(n);
  vii ES;
  FOR(i,n-1) {
    lli u,v;
    cin>>u>>v;
    --u; --v;
    // u = i+1; v = i;
    ES.pb(mt(u,v));
    G[u].pb(v);
    G[v].pb(u);
  }

  vi  A(n,0);
  vi  CP(n,-1);
  vi  DP(n,-1);
  lli root;
  vi pairWith(n,-1);
  FOR(l,100){
    vi E = A;
    vi P(n);
    vi S(n,1);
    function<void(vi&, lli,lli)> dfs0 = [&](vi& C, lli i,lli p){
      E[i]=1; P[i]=p; C.pb(i);
      for(lli j : G[i]) if(!A[j] && j!=p) {
          dfs0(C,j,i);
          S[i]+=S[j];
        }
    };
    vi C;
    FOR(i,n) if(!E[i]) {
      C.clear();
      dfs0(C, i, -1);
      auto f = [&](lli j){
        lli r=0;
        for(auto k : G[j]) if(!A[k] && k!=P[j]) r=max<lli>(r,S[k]);
        r=max<lli>(r,S[i]-S[j]);
        return r;
      };
      vi centroids; lli best=1<<30;
      for(lli j : C) {
        lli v=f(j);
        if(v<best) { centroids.clear(); best=v; }
        if(v==best) centroids.pb(j);
      }
      assert(centroids.size()>=1);
      assert(centroids.size()<=2);
      for(lli j:centroids) A[j]=1;
      if(centroids.size() == 2) {
        pairWith[centroids[0]]=centroids[1];
        pairWith[centroids[1]]=centroids[0];
        CP[centroids[1]]=-1;
      }
      if(CP[centroids[0]]==-1) root=centroids[0];
      function<void(lli,lli,lli,lli)> dfs1 = [&](lli k, lli kk, lli i, lli p){
        if(i!=k) {CP[i]=k;DP[i]=kk;}
        for(lli j : G[i]) if(!A[j] && j!=p) {
            dfs1(k,(kk==-1?j:kk),j,i);
          }
      };
      if(centroids.size() == 1) dfs1(centroids[0],-1,centroids[0],-1);
      else {
        dfs1(centroids[0],-1,centroids[0],centroids[1]);
        dfs1(centroids[1],-1,centroids[1],centroids[0]);
      }
    }
    FOR(i,n) if(!A[i]) goto l_beg;
    break;
  l_beg:;
  }

  vvi H(n); FOR(i,n) if(CP[i]!=-1) H[CP[i]].pb(i);

  vi sz(n,0);
  vi sum(n,0);
  function<void(lli)> dfs3 = [&](lli i0){
    if(pairWith[i0] == -1) {
      sz[i0]=1;
      for(lli j : H[i0]) {
        dfs3(j);
        sz[i0] += sz[j];
        sum[i0] += sum[j]+sz[j];
      }
    }else{
      lli i1 = pairWith[i0];
      sz[i0]=2;
      for(lli j : H[i0]) {
        dfs3(j);
        sz[i0]+=sz[j];
        sum[i0]+=sum[j]+sz[j];
      }
      for(lli j : H[i1]) {
        dfs3(j);
        sz[i0]+=sz[j];
        sum[i0]+=sum[j]+sz[j]+sz[j];
      }
    }
  };
  dfs3(root);

  vector<tpl<lli,lli,lli>> ans;

  function<void(lli,lli,lli)> dfs4 = [&](lli i0, lli p, lli sk) {
    if(pairWith[i0] == -1) {
      for(lli j:H[i0]) sk += sum[j]+sz[j];
      for(lli j : H[i0]) {
        dfs4(j,i0,sk-(sum[j]+sz[j])+(n-(sz[j])));
      }
      if(DP[i0] != -1 && DP[i0] != i0) ans.pb(mt(p,DP[i0],i0));
    }else{
      lli i1 = pairWith[i0];
      lli sz0=1,sm0=0,sz1=1,sm1=0;
      for(lli j:H[i0]) sk += sum[j]+sz[j];
      for(lli j:H[i1]) sk += sum[j]+sz[j];
      for(lli j : H[i0]) {
        dfs4(j,i0,sk-(sum[j]+sz[j])+(n-(sz[j]))+sz[i1]);
        sz0 += sz[j];
        sm0 += sum[j]+sz[j];
      }
      for(lli j : H[i1]) {
        dfs4(j,i1,sk-(sum[j]+sz[j])+(n-(sz[j]))+sz[i0]);
        sz1 += sz[j];
        sm1 += sum[j]+sz[j];
      }
      assert(DP[i0] == DP[i1]);
      if(DP[i0] != -1) {
        int nk = n-(sz0+sz1);
        if(sm1*nk+sm1*sk+sz1*sk<=sm0*nk+sm0*sk+sz0*sk){
          if(DP[i0]!=i0) ans.pb(mt(p,DP[i0],i0));
        }else{
          if(DP[i0]!=i1) ans.pb(mt(p,DP[i0],i1));
        }
      }
    }
  };
  dfs4(root,-1,0);

  reverse(all(ans));
  cout << ans.size() << endl;
  for(auto p : ans) {
    lli x,y,z; tie(x,y,z) = p;
    cout << x+1 << " " << y+1 << " " << z+1 << '\n';
  }
  cout << flush;

  // cerr << H << " " << sz << endl;
  // cerr << ES << endl;
  // test(n,ES,ans);

  // cerr << pairWith << endl;
  // cerr << H << endl;

  return 0;
}

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

#define ms(s, n) memset(s, n, sizeof(s))
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define FORd(i, a, b) for (int i = (a) - 1; i >= (b); i--)
#define FORall(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define sz(a) int((a).size())
#define present(t, x) (t.find(x) != t.end())
#define all(a) (a).begin(), (a).end()
#define uni(a) (a).erase(unique(all(a)), (a).end())
#define pb push_back
#define pf push_front
#define mp make_pair
#define fi first
#define se second
#define prec(n) fixed<<setprecision(n)
#define bit(n, i) (((n) >> (i)) & 1)
#define bitcount(n) __builtin_popcountll(n)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pi> vii;
const int MOD = (int) 1e9 + 7;
const int MOD2 = 1007681537;
const int INF = (int) 1e9;
const ll LINF = (ll) 1e18;
const ld PI = acos((ld) -1);
const ld EPS = 1e-9;
inline ll gcd(ll a, ll b) {ll r; while (b) {r = a % b; a = b; b = r;} return a;}
inline ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
inline ll fpow(ll n, ll k, int p = MOD) {ll r = 1; for (; k; k >>= 1) {if (k & 1) r = r * n % p; n = n * n % p;} return r;}
template<class T> inline int chkmin(T& a, const T& val) {return val < a ? a = val, 1 : 0;}
template<class T> inline int chkmax(T& a, const T& val) {return a < val ? a = val, 1 : 0;}
inline ll isqrt(ll k) {ll r = sqrt(k) + 1; while (r * r > k) r--; return r;}
inline ll icbrt(ll k) {ll r = cbrt(k) + 1; while (r * r * r > k) r--; return r;}
inline void addmod(int& a, int val, int p = MOD) {if ((a = (a + val)) >= p) a -= p;}
inline void submod(int& a, int val, int p = MOD) {if ((a = (a - val)) < 0) a += p;}
inline int mult(int a, int b, int p = MOD) {return (ll) a * b % p;}
inline int inv(int a, int p = MOD) {return fpow(a, p - 2, p);}
inline int sign(ld x) {return x < -EPS ? -1 : x > +EPS;}
inline int sign(ld x, ld y) {return sign(x - y);}
#define db(x) cerr << #x << " = " << (x) << " ";
#define endln cerr << "\n";

const int maxn = 2e5 + 5;
int n;
vi adj[maxn];
int del[maxn];
int size[maxn];

vector<pair<int, pi> > res;

void dfs(int u, int p) {
    size[u] = 1;
    for (int i = 0; i < adj[u].size(); i++) {
        int v = adj[u][i];
        if (v != p && !del[v]) {
            dfs(v, u);
            size[u] += size[v];
        }
    }
}
int findcentroid(int u) {
    int p = -1; dfs(u, -1);
    int cap = size[u] >> 1;
    while (1) {
        bool found = false;
        for (int i = 0; i < adj[u].size(); i++) {
            int v = adj[u][i];
            if (v != p && !del[v] && size[v] > cap) {
                found = true;
                p = u; u = v;
                break;
            }
        }
        if (!found) return u;
    }
}

void dfs(int u, int p, int w, int uu) {
    FOR(i, 0, sz(adj[u])) {
        int v = adj[u][i];
        if (v != p) {
            dfs(v, u, w, uu);
            if (p != w) {
                res.pb(mp(w, mp(uu, v)));
                res.pb(mp(v, mp(u, uu)));
                res.pb(mp(w, mp(v, uu)));
            }
        }
    }
}

void solve() {
    cin >> n;
    FOR(i, 0, n - 1) {
        int u, v; cin >> u >> v; u--, v--;
        adj[u].pb(v), adj[v].pb(u);
    }
    int u = findcentroid(0);
    FOR(i, 0, sz(adj[u])) {
        int v = adj[u][i];
        dfs(v, u, u, v);
    }
    cout << sz(res) << "\n";
    FOR(i, 0, sz(res)) {
        cout << res[i].fi + 1 << " " << res[i].se.fi + 1 << " " << res[i].se.se + 1 << "\n";
    }
}

int main() {
    int JUDGE_ONLINE = 1;
    if (fopen("in.txt", "r")) {
        JUDGE_ONLINE = 0;
        assert(freopen("in.txt", "r", stdin));
        //assert(freopen("out.txt", "w", stdout));
    }
    else {
        ios_base::sync_with_stdio(0), cin.tie(0);
    }
    solve();
    if (!JUDGE_ONLINE) {
        //cout << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
    }
    return 0;
}

#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
int N, M;
vector <int> G[200005];
int Sz[200005], Size[200005];
int sum, cnt;
bool Blocked[200005];
struct Solution{
int x, y, y2;
} S[200005];
bool first;
void Read()
{
    scanf("%d", &N);
    for(int i = 2; i <= N; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
}

void DFS(int node, int father)
{
    Sz[node] = 1;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        DFS(neighb, node);
        Sz[node] += Sz[neighb];
    }
}

int findCentroid(int node, int father, int size)
{
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(neighb == father || Blocked[neighb] == 1)
            continue;
        if(Sz[neighb] > size / 2)
            return findCentroid(neighb, node, size);
    }
    return node;
}

int centroidDecompose(int root)
{
    DFS(root, 0);
    int center = findCentroid(root, 0, Sz[root]);
    Blocked[center] = 1;
    int sz = Sz[root];
    bool ok = 0;
    if(first == 0)
    {
        for(int i = 1; i <= N; i++)
        Size[i] = Sz[i];
        first = 1;
        ok = 1;
    }

    int node = center;
    for(int i = 0; i < G[node].size(); i++)
    {
        int neighb = G[node][i];
        if(Blocked[neighb] == 1)
            continue;
        int n = centroidDecompose(neighb);
        if(n == neighb || (ok == 1 && Size[neighb] == N - Size[neighb]))
            continue;
        ++cnt;
        S[cnt].x = center;
        S[cnt].y = neighb;
        S[cnt].y2 = n;
    }
    return center;
}
int main()
{
    Read();
    centroidDecompose(1);
    printf("%d\n", cnt);
    for(int i = 1; i <= cnt; i++)
    {
        printf("%d %d %d\n", S[i].x, S[i].y, S[i].y2);
    }
    return 0;
}

#include <cstdio>
#include <vector>
#include <algorithm>
#include <stack>
#include <tuple>
#include <set>
#include <iterator>

#define for_each(name, left, right, step) for (int name = left; name < right; name += step)

using namespace std;

typedef pair<int, int> pii;

int operations_made = 0;

vector<int> get_centroids(vector<vector<int> >& node_idx___neigh_idxes) {
    int nodes_nr = node_idx___neigh_idxes.size();
    vector<vector<int> > node_idx___children(nodes_nr);
    vector<int> node_idx___is_visited(nodes_nr, 0);
    stack<int> dfs_stack;
    dfs_stack.push(0);
    node_idx___is_visited[0] = 1;
    while (!dfs_stack.empty()) {
        int curr_node_idx = dfs_stack.top();
        dfs_stack.pop();
        for (auto neigh_idx : node_idx___neigh_idxes[curr_node_idx]) {
            if (!node_idx___is_visited[neigh_idx]) {
                node_idx___is_visited[neigh_idx] = 1;
                node_idx___children[curr_node_idx].push_back(neigh_idx);
                dfs_stack.push(neigh_idx);
            }
        }
    }
    vector<int> node_idx___subnodes_nr(nodes_nr, 1);
    for (auto& is_visited: node_idx___is_visited) {
        is_visited = 0;
    }
    dfs_stack.push(0);
    node_idx___is_visited[0] = 1;
    while (!dfs_stack.empty()) {
        int curr_node_idx = dfs_stack.top();
        bool all_children_visited = true;
        for (auto child_idx : node_idx___children[curr_node_idx]) {
            if (!node_idx___is_visited[child_idx]) {
                node_idx___is_visited[child_idx] = 1;
                dfs_stack.push(child_idx);
                all_children_visited = false;
            }
        }
        if (all_children_visited) {
            for (auto child_idx : node_idx___children[curr_node_idx]) {
                node_idx___subnodes_nr[curr_node_idx] += node_idx___subnodes_nr[child_idx];
            }
            dfs_stack.pop();
        }
    }
    vector<int> centroids;
    for_each(node_idx, 0, nodes_nr, 1) {
        bool is_centroid = true;
        int parent_subnodes = nodes_nr - 1;
        for (auto child_idx: node_idx___children[node_idx]) {
            //cout << node_idx___subnodes_nr[child_idx] << " ";
            if (node_idx___subnodes_nr[child_idx] > nodes_nr / 2) {
                is_centroid = false;
                break;
            }
            parent_subnodes -= node_idx___subnodes_nr[child_idx];
        }
        //cout << parent_subnodes << endl;
        if (parent_subnodes > nodes_nr / 2) {
            is_centroid = false;
        }
        if (is_centroid) {
            centroids.push_back(node_idx);
        }
    }

    return centroids;
}

pii straighten_subtree(int stone_idx, int curr_root_idx, vector<set<int> >& node_idx___neigh_idxes) {
    // cout << "*" << stone_idx << " " << curr_root_idx << endl;
    int neigh_nr = node_idx___neigh_idxes[curr_root_idx].size();
    if (neigh_nr == 1) {
        // cout << "8returned" << endl;
        return make_pair(curr_root_idx, curr_root_idx);
    }
    vector<pii> rel_neigh_idx___root__hangler;
    // int i = 0;
    set<int> curr_neigh_idxes = node_idx___neigh_idxes[curr_root_idx];
    for (auto& neigh_idx: curr_neigh_idxes) {
        if (neigh_idx != stone_idx) {
            rel_neigh_idx___root__hangler.push_back(straighten_subtree(curr_root_idx, neigh_idx, node_idx___neigh_idxes));
            // cout << "***"<< rel_neigh_idx___root__hangler[i].first << " " << rel_neigh_idx___root__hangler[i].second << endl;
            // i++;
        }
    }
    int curr_parent_idx = stone_idx;
    int next_root_idx = (neigh_nr == 2 ? curr_root_idx : rel_neigh_idx___root__hangler[0].second);

    // replace stone_idx curr_root_idx connection
    if (next_root_idx != curr_root_idx) {
        node_idx___neigh_idxes[stone_idx].insert(rel_neigh_idx___root__hangler[0].second);
        auto it = node_idx___neigh_idxes[stone_idx].find(curr_root_idx);
        node_idx___neigh_idxes[stone_idx].erase(it);
        it = node_idx___neigh_idxes[curr_root_idx].find(stone_idx);
        node_idx___neigh_idxes[curr_root_idx].erase(it);
        node_idx___neigh_idxes[rel_neigh_idx___root__hangler[0].second].insert(stone_idx);
        curr_parent_idx = rel_neigh_idx___root__hangler[0].first;
        printf("%d %d %d\n", stone_idx + 1, curr_root_idx + 1, rel_neigh_idx___root__hangler[0].second + 1);
        operations_made++;
        // cout << "**" << operation[0] << " " << operation[1] << " " << operation[2] << endl;
    }
    neigh_nr = rel_neigh_idx___root__hangler.size();
    for_each(neigh_idx, 1, neigh_nr - 1, 1) {
        //create curr_parent_idx, rel_neigh_idx___root__hangler[neigh_idx].second
        printf("%d %d %d\n", curr_parent_idx + 1, curr_root_idx + 1, rel_neigh_idx___root__hangler[neigh_idx].second + 1);
        operations_made++;
        // cout << "**" << operation[0] << " " << operation[1] << " " << operation[2] << endl;
        node_idx___neigh_idxes[curr_parent_idx].insert(rel_neigh_idx___root__hangler[neigh_idx].second);
        node_idx___neigh_idxes[rel_neigh_idx___root__hangler[neigh_idx].second].insert(curr_parent_idx);
        //tear curr_root_idx neigh
        auto it = node_idx___neigh_idxes[curr_parent_idx].find(curr_root_idx);
        node_idx___neigh_idxes[curr_parent_idx].erase(it);
        it = node_idx___neigh_idxes[curr_root_idx].find(curr_parent_idx);
        node_idx___neigh_idxes[curr_root_idx].erase(it);
        curr_parent_idx = rel_neigh_idx___root__hangler[neigh_idx].first;
    }
    // cout << "8returned" << endl;
    return make_pair(next_root_idx, rel_neigh_idx___root__hangler[neigh_nr - 1].second);
}

int hedgehogify(int stone_idx, int curr_root_idx, vector<set<int> >& node_idx___neigh_idxes) {
    int neigh_nr = node_idx___neigh_idxes[curr_root_idx].size();
    // cout << "*" << neigh_nr << endl;
    if (neigh_nr == 1) {
        return curr_root_idx;
    }
    int center_idx;
    for (auto neigh_idx: node_idx___neigh_idxes[curr_root_idx]) {
        if (neigh_idx != stone_idx) {
            center_idx = hedgehogify(curr_root_idx, neigh_idx, node_idx___neigh_idxes);
            // cout << "**" << center_idx << endl;
        }
    }
    printf("%d %d %d\n", stone_idx + 1, curr_root_idx + 1, center_idx + 1);
    operations_made++;
    return center_idx;
}

int straighten_and_hedgehogify_parts(vector<vector<int> >& node_idx___neigh_idxes, int centroid1, int centroid2, bool fl) {
    int nodes_nr = node_idx___neigh_idxes.size();
    int neutral_idx;
    for (auto neigh_idx : node_idx___neigh_idxes[centroid1]) {
        if ((neigh_idx == centroid2) || (neigh_idx == centroid1)) {
            continue;
        }
        vector<set<int> > curr_node_idx___neigh_idxes(nodes_nr);
        curr_node_idx___neigh_idxes[centroid1].insert(neigh_idx);
        curr_node_idx___neigh_idxes[neigh_idx].insert(centroid1);
        vector<int> curr_node_idx___is_visited(nodes_nr, 0);
        stack<int> dfs_stack;
        dfs_stack.push(neigh_idx);
        curr_node_idx___is_visited[neigh_idx] = 1;
        while (!dfs_stack.empty()) {
            int curr_node_idx = dfs_stack.top();
            dfs_stack.pop();
            for (auto curr_neigh_idx: node_idx___neigh_idxes[curr_node_idx]) {
                if ((curr_neigh_idx != centroid1) && (curr_node_idx___is_visited[curr_neigh_idx] == 0) && (curr_neigh_idx != centroid2)) {
                    curr_node_idx___neigh_idxes[curr_node_idx].insert(curr_neigh_idx);
                    curr_node_idx___neigh_idxes[curr_neigh_idx].insert(curr_node_idx);
                    curr_node_idx___is_visited[curr_neigh_idx] = 1;
                    dfs_stack.push(curr_neigh_idx);
                }
            }
        }
        pii report = straighten_subtree(centroid1, neigh_idx, curr_node_idx___neigh_idxes);
        neutral_idx = hedgehogify(centroid1, report.first, curr_node_idx___neigh_idxes);
        // for (auto operation : operations) {
        //     cout << operation[0] << " " << operation[1] << " " << operation[2] << endl;
        // }
    }

    if (centroid1 == centroid2) {
        return neutral_idx;
    }
    if (!fl){
        return straighten_and_hedgehogify_parts(node_idx___neigh_idxes, centroid2, centroid1, 1);
    }
}

void solve() {

    int nodes_nr;
    scanf("%d", &nodes_nr);
    vector<vector<int> > node_idx___neigh_idxes(nodes_nr);
    for_each(edge_idx, 0, nodes_nr - 1, 1) {
        int node1, node2;
        scanf("%d %d", &node1, &node2);
        node1--;
        node2--;
        node_idx___neigh_idxes[node2].push_back(node1);
        node_idx___neigh_idxes[node1].push_back(node2);
    }
    vector<int> centroids = get_centroids(node_idx___neigh_idxes);
    int centroid1, centroid2;
    if (centroids.size() == 1) {
        centroid1 = centroids[0];
        centroid2 = centroids[0];
    }
    else {
        centroid1 = centroids[0];
        centroid2 = centroids[1];
    }
    // cout << "!" << centroid1 << " " << centroid2 << endl;
    vector<vector<int> > operations;
    printf("%d\n", 2 * nodes_nr);
    int neigh_idx = straighten_and_hedgehogify_parts(node_idx___neigh_idxes, centroid1, centroid2, 0);
    while(operations_made < 2 * nodes_nr) {
        printf("%d %d %d\n", centroid2 + 1, neigh_idx + 1, neigh_idx + 1);
        operations_made++;
    }
}

int main() {
    //ios_base::sync_with_stdio(0);
    solve();
}

#include <bits/stdc++.h>
using namespace std;
#define sqr(x) ((x)*(x))
#define par make_pair
#define pb push_back
#define fi first
#define se second
#define endl '\n'
template<class X, class Y> void amax(X& x, const Y& y){if(x < y) x = y;}
template<class X, class Y> void amin(X& x, const Y& y){if(x > y) x = y;}
typedef vector<int> vi; typedef pair<int, int> ii; typedef long long ll; typedef long double ld;
const int INF = 1e9 + 10; const ll INFL = 1e18 + 10;
const int MAX = 2e5 + 10;

struct op{
    int x, y, z;
};

int n, moment, trsz;
vi es[MAX];
vector<op> res;
bool mark[MAX];
ii sz[MAX];

void add_op(const op &x){
    if(x.x == 0 || x.y == x.z) return;
    res.pb(x);
}

void add(ii &p, int value){
    if(p.se < moment) p = par(value, moment);
    else p.fi += value;
}

int dfs_centroid(int u, int p){
    for(auto v : es[u])
    if(!mark[v] && v != p && sz[v].fi > trsz/2) return dfs_centroid(v, u);
    return u;
}

void dfs_size(int u, int p){
    add(sz[u], 1);
    for(auto v : es[u]) if(!mark[v] && v != p){
        dfs_size(v, u);
        add(sz[u], sz[v].fi);
    }
}

void find_centroid(int u, int pc){
    moment++;
    dfs_size(u, 0);
    trsz = sz[u].fi;
    int x = dfs_centroid(u, 0);
    mark[x] = true;
    add_op(op{pc, u, x});
    for(auto v : es[x]) if(!mark[v]) find_centroid(v, x);
}

void process(){
    cin >> n;
    for(int i = 1; i < n; i++){
        int u, v; cin >> u >> v;
        es[u].pb(v); es[v].pb(u);
    }

    find_centroid(1, 0);
    cout << res.size() << endl;
    for(auto v : res) cout << v.x << " " << v.y << " " << v.z << endl;
}

int main(){
    ios_base::sync_with_stdio(false);
    //cin.tie(NULL);
    //freopen("c.in", "r", stdin);
    process();
}

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

const int N = 2 * 1000 * 100 + 10;
int n, par[N], mx[N], sz[N], c1, c2;
vector<int> adj[N], vec;
vector<pair<int, pair<int, int>>> ans;

void dfs(int root, int par = -1) {
	mx[root] = sz[root] = 0;
	for (auto u: adj[root])
		if (u ^ par) {
			dfs(u, root);
			sz[root] += sz[u];
			if (sz[u] > sz[mx[root]])
				mx[root] = u;
		}
	sz[root]++;
}

int centroid(int v) {
	dfs(v);
	while (sz[mx[v]] * 2 > n)
		v = mx[v];
	return v;
}

void dfs2(int root, int p) {
	par[root] = p;
	if (p)
		vec.push_back(root);
	for (auto u: adj[root])
		if (u ^ p)
			dfs2(u, root);
}

void do_shit(int c) {
	if (c < 0)
		return;
	for (auto u: adj[c])
		if (u != c1 && u != c2) {
			vec.clear();
			dfs2(u, c);
			int root = u, tar = u;
			for (auto x: vec) {
				if (x == tar)
					continue;
				if (root != x)
					ans.push_back({c, {root, x}});
				root = x;
				ans.push_back({x, {par[x], tar}});
			}
			if (root != tar)
				ans.push_back({c, {root, tar}});
		}
}

int main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 1, v, u; i < n; i++) {
		cin >> v >> u;
		adj[v].push_back(u);
		adj[u].push_back(v);
	}
	int c1 = centroid(1), c2 = -1;
	if (n % 2 == 0)
		c2 = mx[c1];
	do_shit(c1), do_shit(c2);
	cout << (int)(ans.size()) << '\n';
	for (auto it: ans)
		cout << it.first << ' ' << it.second.first << ' ' << it.second.second << '\n';
	return 0;
}