#include <bits/stdc++.h>
using namespace std;
const int inf = 1 << 30;
const int M = 2e7 + 5;
int n, m, S, T, cnt;
struct Flow {
  int head[(int(5e5 + 5))], depth[(int(5e5 + 5))], vis[(int(5e5 + 5))],
      pos[(int(5e5 + 5))], stack[(int(5e5 + 5))], top;
  struct graph {
    int next, to, val;
    graph() {}
    graph(int _next, int _to, int _val) : next(_next), to(_to), val(_val) {}
  } edge[M];
  inline void init() {
    cnt = m;
    S = ++cnt, T = ++cnt;
  }
  inline void add(int x, int y, int z) {
    static int Cnt = 1;
    edge[++Cnt] = graph(head[x], y, z);
    head[x] = Cnt;
    edge[++Cnt] = graph(head[y], x, 0);
    head[y] = Cnt;
  }
  inline bool BFS() {
    memset(depth, -1, sizeof depth);
    queue<int> q;
    q.push(S);
    depth[S] = 0;
    while (!q.empty()) {
      int tt = q.front();
      q.pop();
      for (int i = head[tt]; i; i = edge[i].next) {
        if (edge[i].val && depth[edge[i].to] < 0) {
          depth[edge[i].to] = depth[tt] + 1;
          q.push(edge[i].to);
        }
      }
    }
    return ~depth[T];
  }
  inline int DFS(int x, int f) {
    if (x == T) return f;
    int used = 0, w;
    for (int i = head[x]; i; i = edge[i].next) {
      if (depth[edge[i].to] == depth[x] + 1 && edge[i].val) {
        w = DFS(edge[i].to, min(edge[i].val, f - used));
        edge[i].val -= w, edge[i ^ 1].val += w, used += w;
        if (used == f) return used;
      }
    }
    depth[x] = -1;
    return used;
  }
  inline void DFS1(int x) {
    vis[x] = 1;
    for (int i = head[x]; i; i = edge[i].next) {
      if (!vis[edge[i].to] && edge[i].val) {
        DFS1(edge[i].to);
      }
    }
  }
  inline void solve() {
    int ans = 0;
    while (BFS()) ans += DFS(S, inf);
    cout << ans << endl;
    DFS1(S);
    top = 0;
    for (int i = head[S]; i; i = edge[i].next)
      if (!vis[edge[i].to]) stack[++top] = edge[i].to;
    printf("%d ", top);
    for (int i = 1; i <= top; ++i) printf("%d ", stack[i]);
    puts("");
    top = 0;
    for (int i = head[T]; i; i = edge[i].next)
      if (vis[edge[i].to]) stack[++top] = pos[edge[i].to];
    printf("%d ", top);
    for (int i = 1; i <= top; ++i) printf("%d ", stack[i]);
    puts("");
  }
} net;
struct tree {
  int head[((int)(2e4 + 5))], depth[((int)(2e4 + 5))], F[((int)(2e4 + 5))][16],
      P[((int)(2e4 + 5))][16];
  struct graph {
    int next, to;
    graph() {}
    graph(int _next, int _to) : next(_next), to(_to) {}
  } edge[((int)(2e4 + 5)) << 1];
  inline void add(int x, int y) {
    static int cnt = 1;
    edge[++cnt] = graph(head[x], y);
    head[x] = cnt;
    edge[++cnt] = graph(head[y], x);
    head[y] = cnt;
  }
  void DFS(int x) {
    for (int i = 1; i <= 15; ++i) {
      F[x][i] = F[F[x][i - 1]][i - 1];
      P[x][i] = ++cnt;
      if (F[x][i]) {
        net.add(P[x][i], P[x][i - 1], inf);
        net.add(P[x][i], P[F[x][i - 1]][i - 1], inf);
      }
    }
    for (int i = head[x]; i; i = edge[i].next) {
      if (edge[i].to != F[x][0]) {
        F[edge[i].to][0] = x;
        P[edge[i].to][0] = ++cnt;
        depth[edge[i].to] = depth[x] + 1;
        net.pos[cnt] = i >> 1;
        net.add(P[edge[i].to][0], T, 1);
        DFS(edge[i].to);
      }
    }
  }
  void find(int x, int y, int tmp) {
    net.add(S, tmp, 1);
    if (depth[x] < depth[y]) swap(x, y);
    int tt = depth[x] - depth[y];
    for (int i = 0; i <= 15; ++i)
      if ((1 << i) & tt) net.add(tmp, P[x][i], inf), x = F[x][i];
    for (int i = 15; i >= 0; --i)
      if (F[x][i] != F[y][i]) {
        net.add(tmp, P[x][i], inf);
        net.add(tmp, P[y][i], inf);
        x = F[x][i], y = F[y][i];
      }
    if (x == y) return;
    net.add(tmp, P[x][0], inf);
    net.add(tmp, P[y][0], inf);
  }
} tr;
inline int read() {
  int x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = (x << 1) + (x << 3) + ch - '0';
    ch = getchar();
  }
  return x * f;
}
int main() {
  n = read(), m = read();
  for (int i = 1; i < n; ++i) tr.add(read(), read());
  net.init();
  tr.DFS(1);
  for (int i = 1; i <= m; ++i) {
    int x = read(), y = read();
    tr.find(x, y, i);
  }
  net.solve();
}
