#include <bits/stdc++.h>
using namespace std;
int ri() {
  int x;
  scanf("%d", &x);
  return x;
}
const int N = 500000;
namespace LCT {
extern struct Node null;
struct Edge;
struct Node {
  int flip, w;
  Node *c[2], *p, *opt;
  void init() {
    c[0] = c[1] = p = &null;
    flip = 0;
    w = -1;
    opt = this;
  }
  void mconcat() {
    opt = this;
    if (c[0]->opt->w > opt->w) opt = c[0]->opt;
    if (c[1]->opt->w > opt->w) opt = c[1]->opt;
  }
  void setc(int d, Node *x) {
    c[d] = x;
    x->p = this;
  }
  void untag() {
    if (!flip) return;
    flip = 0;
    c[0]->flip ^= 1;
    c[1]->flip ^= 1;
    swap(c[0], c[1]);
  }
  void zag(int d) {
    Node *x = c[d], *p = this->p;
    setc(d, x->c[d ^ 1]);
    mconcat();
    x->setc(d ^ 1, this);
    x->p = p;
    if (p->c[0] == this)
      p->c[0] = x;
    else if (p->c[1] == this)
      p->c[1] = x;
  }
  void splay() {
    while (p->c[0] == this || p->c[1] == this) {
      Node *p = this->p, *g = p->p;
      if (g->c[0] == p || g->c[1] == p) {
        g->untag();
        p->untag();
        untag();
        if (g->c[0] == p) {
          if (p->c[0] == this)
            g->zag(0), p->zag(0);
          else
            p->zag(1), g->zag(0);
        } else {
          if (p->c[0] != this)
            g->zag(1), p->zag(1);
          else
            p->zag(0), g->zag(1);
        }
      } else {
        p->untag();
        untag();
        p->zag(p->c[0] != this);
      }
    }
    untag();
    mconcat();
  }
  void expose() {
    Node *x = this, *y = &null;
    for (; x != &null; y = x, x = x->p) {
      x->splay();
      x->c[1] = y;
    }
    splay();
  }
  void evert() {
    expose();
    flip = 1;
  }
  bool same_root(Node *o) {
    expose();
    o->expose();
    return p != &null;
  }
  void link(Node *o) {
    o->evert();
    o->p = this;
  }
  void cut(Node *o) {
    evert();
    o->expose();
    p = &null;
    o->setc(0, &null);
    o->mconcat();
  }
  Edge *query(Node *o) {
    evert();
    o->expose();
    return (Edge *)o->opt;
  }
} null, nodes[N];
struct Edge : Node {
  Node *x, *y;
} edges[N];
};  // namespace LCT
int main() {
  int n = ri();
  map<pair<int, int>, LCT::Edge *> edge;
  vector<pair<int, int>> queries;
  vector<pair<pair<int, int>, pair<int, int>>> ans;
  LCT::null.init();
  for (int i = 0; i < (n); i++) LCT::nodes[i].init();
  for (int i = 0; i < (n - 1); i++) {
    int u = ri() - 1, v = ri() - 1;
    if (u > v) swap(u, v);
    LCT::Edge *e = &LCT::edges[i];
    edge[{u, v}] = e;
    e->init();
    e->x = &LCT::nodes[u];
    e->y = &LCT::nodes[v];
    e->w = 1;
    e->mconcat();
    e->link(e->x);
    e->link(e->y);
  }
  for (int i = 0; i < (n - 1); i++) {
    int u = ri() - 1, v = ri() - 1;
    if (u > v) swap(u, v);
    if (edge.count(pair<int, int>{u, v})) {
      LCT::Edge *e = edge[{u, v}];
      e->expose();
      e->w = 0;
      e->mconcat();
    } else
      queries.emplace_back(u, v);
  }
  for (auto &q : queries) {
    int u, v;
    tie(u, v) = q;
    auto e = LCT::nodes[u].query(&LCT::nodes[v]);
    ans.emplace_back(pair<int, int>{e->x - LCT::nodes, e->y - LCT::nodes},
                     pair<int, int>{u, v});
    e->cut(e->x);
    e->cut(e->y);
    e->x = &LCT::nodes[u];
    e->y = &LCT::nodes[v];
    e->link(e->x);
    e->link(e->y);
    e->w = -1;
    e->mconcat();
  }
  printf("%lu\n", ans.size());
  for (auto &x : ans)
    printf("%d %d %d %d\n", x.first.first + 1, x.first.second + 1,
           x.second.first + 1, x.second.second + 1);
}
