You are given a tree with n vertices and you are allowed to perform no more than 2n transformations on it. Transformation is defined by three vertices x, y, y' and consists of deleting edge (x, y) and adding edge (x, y'). Transformation x, y, y' could be performed if all the following conditions are satisfied:  There is an edge (x, y) in the current tree.  After the transformation the graph remains a tree.  After the deletion of edge (x, y) the tree would consist of two connected components. Let's denote the set of nodes in the component containing vertex x by Vx, and the set of nodes in the component containing vertex y by Vy. Then condition |Vx| > |Vy| should be satisfied, i.e. the size of the component with x should be strictly larger than the size of the component with y. You should minimize the sum of squared distances between all pairs of vertices in a tree, which you could get after no more than 2n transformations and output any sequence of transformations leading initial tree to such state.Note that you don't need to minimize the number of operations. It is necessary to minimize only the sum of the squared distances.

The first line of input contains integer n (1 ≤ n ≤ 2·105) — number of vertices in tree. The next n - 1 lines of input contains integers a and b (1 ≤ a, b ≤ n, a ≠ b) — the descriptions of edges. It is guaranteed that the given edges form a tree.

In the first line output integer k (0 ≤ k ≤ 2n) — the number of transformations from your example, minimizing sum of squared distances between all pairs of vertices. In each of the next k lines output three integers x, y, y' — indices of vertices from the corresponding transformation. Transformations with y = y' are allowed (even though they don't change tree) if transformation conditions are satisfied. If there are several possible answers, print any of them.

NoteThis is a picture for the second sample. Added edges are dark, deleted edges are dotted.

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

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 <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 <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 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 <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;
}

/* "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>
#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;
#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>
#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 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);
	}
}

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

/*
СТРОИМ СТЕНУ РАБОТЯГИ!
█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█
█═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═█
█═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═█
█═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═█
█═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═█
█═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═█
█═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═█
█═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═█
█═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═╩═╦═█
█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█
*/
#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;
}

// 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;
}

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

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 );
}

#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 <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);
    }

}

#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;
}

#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;
#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";
}

#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 <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 <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;
}

#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;
}

#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
*/

#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<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;
}

#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;
}

#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 <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 <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;
}

#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>
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;
}

#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);
}

/* "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;
#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
*/

// :(
#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;

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;
}

// {{{
//#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;
#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

#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;

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<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<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 <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<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;
}

#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

 */

#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;
}

#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;
}

#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;
}

// 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;
}

/**
 * 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>
#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>

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;
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<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 <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;
}

/*"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 <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 <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);
	}
}

// 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>
#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 <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 <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>

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 );
}

#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;
}

#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 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 <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;
}

#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>
#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;
}

///****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>
#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 <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 <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 <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>

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 <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);

}

#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, 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 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;
#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;
}