#include <bits/stdc++.h>
using namespace std;
const double pi = acos(0) * 2;
template <class T>
inline T abs1(T a) {
  return a < 0 ? -a : a;
}
template <class T>
inline T max1(T a, T b) {
  return a > b ? a : b;
}
template <class T>
inline T min1(T a, T b) {
  return a < b ? a : b;
}
template <class T>
inline T gcd1(T a, T b) {
  if (a < b) swap(a, b);
  if (a % b == 0) return b;
  return gcd1(b, a % b);
}
template <class T>
inline T lb(T num) {
  return num & (-num);
}
template <class T>
inline int bitnum(T num) {
  int ans = 0;
  while (num) {
    num -= lb(num);
    ans++;
  }
  return ans;
}
long long pow(long long n, long long m, long long mod = 0) {
  long long ans = 1;
  long long k = n;
  while (m) {
    if (m & 1) {
      ans *= k;
      if (mod) ans %= mod;
    }
    k *= k;
    if (mod) k %= mod;
    m >>= 1;
  }
  return ans;
}
const int maxn = 101000;
int n, lans;
vector<int> edge[maxn], be[maxn];
int ledge1, edge1[maxn][2];
int ji[maxn][2];
void dfs(int no, int fa, int edgefa) {
  for (int i = 0; i < edge[no].size(); i++) {
    if (edge[no][i] == fa) continue;
    ji[lans][0] = no;
    ji[lans][1] = edge[no][i];
    be[no].push_back(lans++);
    dfs(edge[no][i], no, lans - 1);
  }
  if (edgefa == -1)
    for (int i = 0; i < be[no].size() - 1; i++) {
      edge1[ledge1][0] = be[no][i];
      edge1[ledge1++][1] = be[no][i + 1];
    }
  else
    for (int i = 0; i < be[no].size(); i++) {
      edge1[ledge1][0] = be[no][i];
      edge1[ledge1++][1] = edgefa;
    }
}
int main() {
  scanf("%d", &n);
  for (int i = 0; i < n - 1; i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    a--;
    b--;
    edge[a].push_back(b);
    edge[b].push_back(a);
  }
  dfs(0, -1, -1);
  printf("%d\n", lans);
  for (int i = 0; i < lans; i++)
    printf("2 %d %d\n", ji[i][0] + 1, ji[i][1] + 1);
  for (int i = 0; i < ledge1; i++)
    printf("%d %d\n", edge1[i][0] + 1, edge1[i][1] + 1);
  return 0;
}
