#include <bits/stdc++.h>
using namespace std;
const int N = 2e4, M = 1e4, MAX_D = 15, inf = 1e8;
namespace MaxFlow {
const int MAX_V = 1 + N + M + (MAX_D + 1) * (N - 1);
struct Edge {
  int u, v, c;
};
vector<Edge> E;
vector<int> adj[MAX_V];
queue<int> Q;
int cur[MAX_V], level[MAX_V];
bool mark[MAX_V];
inline void add(int u, int v, int f) {
  adj[u].push_back(E.size());
  E.push_back((Edge){u, v, f});
  adj[v].push_back(E.size());
  E.push_back((Edge){v, u, 0});
}
bool bfs(const int& s, const int& t, const int& n) {
  fill_n(level, n, -1);
  level[s] = 0;
  Q.push(s);
  while (!Q.empty()) {
    int u = Q.front();
    Q.pop();
    for (int i = (0), i_ = (adj[u].size()); i < i_; ++i) {
      Edge& e = E[adj[u][i]];
      if (e.c && level[e.v] == -1) {
        level[e.v] = level[u] + 1;
        Q.push(e.v);
      }
    }
  }
  return ~level[t];
}
int dfs(int u, int f, const int& t) {
  if (u == t) return f;
  int in = f, d;
  for (int& i = cur[u]; i < (int)adj[u].size(); ++i) {
    Edge& e = E[adj[u][i]];
    if (level[e.v] == level[u] + 1 && e.c && (d = dfs(e.v, min(f, e.c), t))) {
      e.c -= d;
      E[adj[u][i] ^ 1].c += d;
      if (!(f -= d)) break;
    }
  }
  return in - f;
}
void dfs1(int u) {
  mark[u] = true;
  for (int i = (0), i_ = (adj[u].size()); i < i_; ++i) {
    Edge& e = E[adj[u][i]];
    if (e.c && !mark[e.v]) dfs1(e.v);
  }
}
int max_flow(int s, int t, int n) {
  int f = 0;
  while (bfs(s, t, n)) {
    fill_n(cur, n, 0);
    f += dfs(s, inf, t);
  }
  dfs1(s);
  return f;
}
}  // namespace MaxFlow
using MaxFlow::add;
int n, m;
namespace Doubling {
struct Edge {
  int v, e;
};
vector<Edge> adj[N + 1];
int anc[N + 1][MAX_D + 1], dep[N + 1], D;
inline void add_edge(int u, int v, int e) {
  adj[u].push_back((Edge){v, e});
  adj[v].push_back((Edge){u, e});
}
void dfs(int u, int p) {
  anc[u][0] = p;
  for (int i = (1), i_ = (D); i <= i_; ++i) {
    anc[u][i] = anc[anc[u][i - 1]][i - 1];
    if (anc[u][i]) {
      add((n + m + (D + 1) * ((u)-2) + (i) + 1),
          (n + m + (D + 1) * ((u)-2) + (i - 1) + 1), inf);
      add((n + m + (D + 1) * ((u)-2) + (i) + 1),
          (n + m + (D + 1) * ((anc[u][i - 1]) - 2) + (i - 1) + 1), inf);
    }
  }
  for (int i = (0), i_ = (adj[u].size()); i < i_; ++i) {
    Edge& e = adj[u][i];
    if (e.v != p) {
      add((n + m + (D + 1) * ((e.v) - 2) + (0) + 1), e.e, inf);
      dep[e.v] = dep[u] + 1;
      dfs(e.v, u);
    }
  }
}
void path(int num, int u, int v) {
  num += n;
  if (dep[u] > dep[v]) swap(u, v);
  for (int h = dep[v] - dep[u], i = 0; h; h >>= 1, ++i)
    if (h & 1) {
      add(num, (n + m + (D + 1) * ((v)-2) + (i) + 1), 1);
      v = anc[v][i];
    }
  if (u == v) return;
  for (int i = (D), i_ = (0); i >= i_; --i)
    if (anc[u][i] != anc[v][i]) {
      add(num, (n + m + (D + 1) * ((u)-2) + (i) + 1), inf);
      add(num, (n + m + (D + 1) * ((v)-2) + (i) + 1), inf);
      u = anc[u][i];
      v = anc[v][i];
    }
  add(num, (n + m + (D + 1) * ((u)-2) + (0) + 1), 1);
  add(num, (n + m + (D + 1) * ((v)-2) + (0) + 1), 1);
}
}  // namespace Doubling
inline void print(int fr, int to, bool b) {
  using MaxFlow::mark;
  int cnt = 0;
  for (int i = (fr), i_ = (to); i <= i_; ++i) cnt += mark[i] == b;
  printf("%d ", cnt);
  for (int i = (fr), i_ = (to); i <= i_; ++i)
    if (mark[i] == b) printf("%d ", i - fr + 1);
  puts("");
}
int main() {
  scanf("%d%d", &n, &m);
  using Doubling::D;
  while ((1 << D) < n - 1) ++D;
  for (int i = (1), i_ = (n - 1); i <= i_; ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    Doubling::add_edge(u, v, i);
    add(i, n, 1);
  }
  Doubling::dfs(1, 0);
  for (int i = (1), i_ = (m); i <= i_; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    Doubling::path(i, x, y);
    add(0, n + i, 1);
  }
  int flow = MaxFlow::max_flow(0, n, 1 + n + m + (D + 1) * (n - 1));
  printf("%d\n", flow);
  print(n + 1, n + m, false);
  print(1, n - 1, true);
  return 0;
}
