#include <bits/stdc++.h>   using namespace std;   struct LCA {     int logn;     vector<int> depth;     vector<vector<int> > lca;     vector<vector<int> > *edges;     LCA(int n, vector<vector<int> > *edges) {       logn = log(n) / log(2) + 1;       depth.resize(n + 1, 0);       lca.resize(n + 1, vector<int>(logn, 0));       this->edges = edges;       build();     }     void dfs(int u, int p) {       lca[u][0] = p;       for (int i = 1; i < logn; i++) {         lca[u][i] = lca[lca[u][i - 1]][i - 1];       }       depth[u] = depth[p] + 1;       for (auto &v : (*edges)[u]) {         if (p != v) {           dfs(v, u);         }       }     }     int parent(int v, int h) {       for (int i = logn - 1; i >= 0; i--) {         if (h & (1 << i)) {           v = lca[v][i];         }       }       return v;     }     int lessParent(int u, int p) { return parent(u, depth[u] - depth[p] - 1); }     int get(int u, int v) {       if (depth[u] > depth[v]) {         swap(u, v);       }       int h = depth[v] - depth[u];       v = parent(v, h);       if (u == v) {         return u;       }       for (int i = logn - 1; i >= 0; i--) {         if (lca[u][i] != lca[v][i]) {           u = lca[u][i];           v = lca[v][i];         }       }       return lca[u][0];     }     void build() { dfs(1, 0); }   } * lca;   struct GraphBuilder {     enum DIRECT {       UP = 0,       DOWN,     };     int n;     int k;     vector<vector<int> > *e;     vector<pair<int, int> > edges;     set<pair<int, int> > cache;     vector<vector<int> > addedVertices;     vector<vector<int> > deletedVertices;     LCA *lca;     struct Node {       int id;       Node *leftChild;       Node *rightChild;       Node(int v, Node *l, Node *r) {         id = v;         leftChild = l;         rightChild = r;       }     };     vector<pair<Node *, Node *> > root;     GraphBuilder(int m, vector<vector<int> > *e) {       k = 2 * m - 1;       n = 2 * m - 1;       this->e = e;       lca = new LCA(e->size() - 1, e);       addedVertices.resize(e->size());       deletedVertices.resize(e->size());       for (int i = 0; i < m; i++) {         for (int j = 0; j < 2; j++) {           int u, v;           scanf( %d %d , &u, &v);           int p = lca->get(u, v);           if (u != p) {             addedVertices[u].push_back((i << 1) | j);             deletedVertices[lca->lessParent(u, p)].push_back((i << 1) | j);           }           if (v != p) {             addedVertices[v].push_back((i << 1) | j);             deletedVertices[lca->lessParent(v, p)].push_back((i << 1) | j);           }         }       }       root.resize(e->size(), {0, 0});       dfs(1, 0);     }     void dfs(int u, int p) {       for (auto &v : (*e)[u]) {         if (v != p) {           dfs(v, u);           root[u].first = merge(root[u].first, root[v].first, DOWN);           root[u].second = merge(root[u].second, root[v].second, UP);         }       }       for (auto &x : addedVertices[u]) {         root[u].first = addVertex(0, n, root[u].first, (x ^ 1), DOWN);         root[u].second = addVertex(0, n, root[u].second, x, UP);       }       for (auto &x : deletedVertices[u]) {         root[u].first = delVertex(0, n, root[u].first, (x ^ 1), DOWN);         root[u].second = delVertex(0, n, root[u].second, x, UP);         if (root[u].first) {           add(x, root[u].first->id);         }         if (root[u].second) {           add(root[u].second->id, (x ^ 1));         }       }     }     void add(int u, int v) { edges.push_back({u, v}); }     void addEdge(Node *p, int direct) {       if (direct == DOWN) {         if (p->leftChild) {           add(p->id, p->leftChild->id);         }         if (p->rightChild) {           add(p->id, p->rightChild->id);         }       } else {         if (p->leftChild) {           add(p->leftChild->id, p->id);         }         if (p->rightChild) {           add(p->rightChild->id, p->id);         }       }     }     Node *addVertex(int l, int r, Node *p, int v, int direct) {       if (!p) {         p = new Node(0, 0, 0);       }       if (l == r) {         return new Node(v, 0, 0);       } else {         int mid = (l + r) >> 1;         Node *newNode = new Node(++k, p->leftChild, p->rightChild);         if (v <= mid) {           newNode->leftChild = addVertex(l, mid, p->leftChild, v, direct);         } else {           newNode->rightChild = addVertex(mid + 1, r, p->rightChild, v, direct);         }         addEdge(newNode, direct);         return newNode;       }     }     Node *delVertex(int l, int r, Node *p, int v, int direct) {       if (l == r) {         return 0;       } else {         int mid = (l + r) >> 1;         Node *newNode = new Node(++k, p->leftChild, p->rightChild);         if (v <= mid) {           newNode->leftChild = delVertex(l, mid, p->leftChild, v, direct);         } else {           newNode->rightChild = delVertex(mid + 1, r, p->rightChild, v, direct);         }         if (!newNode->leftChild && !newNode->rightChild) {           return 0;         }         addEdge(newNode, direct);         return newNode;       }     }     Node *merge(Node *p1, Node *p2, int direct) {       if (!p1 || !p2) {         return p1 ? p1 : p2;       } else {         Node *left = merge(p1->leftChild, p2->leftChild, direct);         Node *right = merge(p1->rightChild, p2->rightChild, direct);         Node *newNode = new Node(++k, left, right);         addEdge(newNode, direct);         return newNode;       }     }   };   struct SAT {     int n;     vector<int> st;     vector<int> mark;     vector<int> group;     vector<vector<int> > edges;     vector<vector<int> > revEdges;     SAT(int n, vector<pair<int, int> > &e) {       this->n = n + 1;       mark.resize(n + 1, 0);       group.resize(n + 1, 0);       edges.resize(n + 1);       revEdges.resize(n + 1);       for (auto &p : e) {         addEdge(p.first, p.second);       }     }     void addEdge(int u, int v) {       edges[u].push_back(v);       revEdges[v].push_back(u);     }     void dfs1(int u) {       mark[u] = 1;       for (auto &v : edges[u]) {         if (mark[v] == 0) {           dfs1(v);         }       }       st.push_back(u);     }     void dfs2(int u, int k) {       group[u] = k;       for (auto &v : revEdges[u]) {         if (group[v] == 0) {           dfs2(v, k);         }       }     }     void solve() {       for (int i = 0; i < n; i++) {         if (mark[i] == 0) {           dfs1(i);         }       }       int k = 0;       for (int i = st.size() - 1; i >= 0; i--) {         int u = st[i];         if (group[u] == 0) {           k++;           dfs2(u, k);         }       }     }     void answer(int m) {       for (int i = 0; i < 2 * m; i += 2) {         if (group[i] == group[i | 1]) {           printf( NO );           return;         }       }       printf( YES n );       for (int i = 0; i < 2 * m; i += 2) {         printf( %d n , (group[i] > group[i | 1]) ? 1 : 2);       }     }   };   int main() {     int n;     scanf( %d , &n);     vector<vector<int> > edges(n + 1);     for (int i = 1; i < n; i++) {       int u, v;       scanf( %d %d , &u, &v);       edges[u].push_back(v);       edges[v].push_back(u);     }     int m;     scanf( %d , &m);     GraphBuilder builder(m, &edges);     SAT solver(builder.k, builder.edges);     solver.solve();     solver.answer(m);   }   