#include <bits/stdc++.h>   using namespace std;   const int N = 1e5 + 10, M = 1e6 + 10, K = 2e4 + 10;   int head[N], h2[N], cur[N], dep[N], to[M], lim[M], nxt[M], vis[N], cnt = 1, n,                                                                      m, s, t;   void add_edge(int u, int v, int l, int *head) {     nxt[++cnt] = head[u], head[u] = cnt, lim[cnt] = l, to[cnt] = v;     nxt[++cnt] = head[v], head[v] = cnt, lim[cnt] = 0, to[cnt] = u;   }   bool bfs() {     queue<int> q;     memset(dep, 0x3f, sizeof(dep));     memset(vis, 0, sizeof(vis));     memcpy(cur, head, sizeof(cur));     dep[s] = 0;     q.push(s);     while (!q.empty()) {       int h = q.front();       vis[h] = 0;       q.pop();       for (int i = head[h]; i; i = nxt[i])         if ((dep[to[i]] > dep[h] + 1) && lim[i]) {           dep[to[i]] = dep[h] + 1;           if (!vis[to[i]]) vis[to[i]] = 1, q.push(to[i]);         }     }     if (dep[t] != 0x3f3f3f3f) return true;     return false;   }   long long dfs(int rt = s, long long flow = 1e18) {     if (rt == t) return flow;     long long f = 0, ans = 0;     for (int i = cur[rt]; i; i = nxt[i]) {       cur[rt] = i;       if (lim[i] && dep[to[i]] == dep[rt] + 1) {         f = dfs(to[i], min(flow - ans, 1ll * lim[i]));         if (f) {           lim[i] -= f;           lim[i ^ 1] += f;           ans += f;           if (ans == flow) break;         }       }     }     return ans;   }   long long dinic() {     long long ans = 0, flow;     while (bfs()) {       while (flow = dfs()) ans += flow;     }     return ans;   }   vector<int> ans, edg;   int nd, P[N], Q[N], Dep[K], fa[K], siz[K], son[K], top[K], id[K], tim, eid[N];   bool _vis[N];   void dfs1(int rt, int f, int e = 0) {     fa[rt] = f, siz[rt] = 1, Dep[rt] = Dep[f] + 1, eid[rt] = e;     for (int i = h2[rt]; i; i = nxt[i])       if (to[i] != f) {         dfs1(to[i], rt, lim[i]);         siz[rt] += siz[to[i]];         if (siz[to[i]] > top[rt]) top[rt] = siz[to[i]], son[rt] = to[i];       }   }   void dfs2(int rt, int t) {     top[rt] = t, id[rt] = ++tim;     if (son[rt]) dfs2(son[rt], t);     for (int i = h2[rt]; i; i = nxt[i])       if (to[i] != fa[rt] && to[i] != son[rt]) dfs2(to[i], to[i]);   }   void dfs3(int rt) {     vis[rt] = 1;     for (int i = head[rt]; i; i = nxt[i])       if (lim[i] && !vis[to[i]]) dfs3(to[i]);   }   void build(int l = 1, int r = n, int rt = 1) {     P[rt] = ++nd;     if (l == r) return Q[l] = P[rt], add_edge(P[rt], t, 1, head);     int mid = (l + r) >> 1;     build(l, mid, (rt << 1)), build(mid + 1, r, ((rt << 1) | 1));     add_edge(P[rt], P[(rt << 1)], 1e9, head),         add_edge(P[rt], P[((rt << 1) | 1)], 1e9, head);   }   void _add_edges(int L, int R, int u, int l = 1, int r = n, int rt = 1) {     if (L <= l && r <= R) return add_edge(u, P[rt], 1e9, head);     int mid = (l + r) >> 1;     if (L <= mid) _add_edges(L, R, u, l, mid, (rt << 1));     if (R > mid) _add_edges(L, R, u, mid + 1, r, ((rt << 1) | 1));   }   void add_edges(int u, int v, int from) {     while (top[u] != top[v]) {       if (Dep[top[u]] < Dep[top[v]]) swap(u, v);       _add_edges(id[top[u]], id[u], from);       u = fa[top[u]];     }     if (Dep[u] > Dep[v]) swap(u, v);     if (u == v) return;     _add_edges(id[u] + 1, id[v], from);   }   int main() {     ios::sync_with_stdio(false);     cin >> n >> m;     int u, v;     for (int i = 1; i < n; ++i)       cin >> u >> v, add_edge(u, v, i, h2), lim[cnt] = i;     dfs1(1, 0);     dfs2(1, 1);     nd = m;     s = ++nd, t = ++nd;     build();     for (int i = 1; i <= m; ++i) add_edge(s, i, 1, head);     for (int i = 1; i <= m; ++i) {       cin >> u >> v;       add_edges(u, v, i);     }     cout << dinic() << endl;     dfs3(s);     for (int i = 1; i <= m; ++i)       if (!vis[i]) ans.push_back(i);     for (int i = 2; i <= n; ++i)       if (vis[Q[id[i]]]) edg.push_back(eid[i]);     cout << ans.size() <<    ;     for (auto i : ans) cout << i <<    ;     cout << endl << edg.size() <<    ;     for (auto i : edg) cout << i <<    ;   }