题意:这道题和我上一篇发的题很像,题意是这样,给你一棵树,然后
给出m条路,让你求出一个最小点集,使得这个点集包含每一条路中最少一个点。
思路:树链剖分,然后求出m对路的lca,按照他们的lca深度从深到浅排序,
然后从深到浅开始dfs,每次dfs求出这一对点各自的链首,找出较深的那一个,
询问那一点到其链首中有没有点已经被选过,然后把那一点更新为那一点的链首的父亲的
链首。
题目链接

#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 10;
typedef long long ll;
int n, m, u[N], v[N];
vector<int> G[N];
int lc[N], ans;
int fa[N], dep[N], idx[N], out[N], ridx[N];

struct Edge
{
    int u, v, lca;
    bool operator < (const Edge &e) const
    {
        return dep[lca] > dep[e.lca];
    }
};
Edge edges[N];

struct BIT
{
    int c[N];
    void init()
    {
        memset(c, 0, sizeof c);
    }
    void add(int x, int d)
    {
        for (x++; x < N; x += x & -x)
            c[x] += d;
    }

    int query(int x)
    {
        int ret = 0;
        for (x++; x; x -= x & -x)
            ret += c[x];
        return ret;
    }
} bit;

namespace hld
{
int sz[N], son[N], top[N], clk;
void init()
{
    clk = 0;
}
void predfs(int u, int d)
{
    dep[u] = d;
    sz[u] = 1;
    int& maxs = son[u] = -1;
    for (int& v: G[u])
    {
        if (v == fa[u]) continue;
        fa[v] = u;
        predfs(v, d + 1);
        sz[u] += sz[v];
        if (maxs == -1 || sz[v] > sz[maxs]) maxs = v;
    }
}
void dfs(int u, int tp)
{
    top[u] = tp;
    idx[u] = ++clk;
    ridx[clk] = u;
    if (son[u] != -1) dfs(son[u], tp);
    for (int& v: G[u])
        if (v != fa[u] && v != son[u]) dfs(v, v);
    out[u] = clk;
}
template<typename T>
int go(int u, int v, T&& f)
{
  // cout<<endl<<endl<<"******"<<endl;
    int uu = top[u], vv = top[v];
   // cout<<uu<<" "<<vv<<" "<<u<<" "<<v<<endl;
    while (uu != vv)
    {
        if (dep[uu] < dep[vv])
        {
            swap(uu, vv);
            swap(u, v);
        }
       // cout<<uu<<" "<<u<<" "<<idx[uu]<<" "<<idx[u]<<"dfs序"<<endl;
        f(idx[uu], idx[u]);
        u = fa[uu];
        uu = top[u];
      // cout<<uu<<" "<<vv<<" "<<u<<" "<<v<<endl;
    }
    if (dep[u] < dep[v]) swap(u, v);
    // choose one
    f(idx[v], idx[u]);
    // if (u != v) f(idx[v] + 1, idx[u]);
   // cout<<endl<<endl<<"******"<<endl;
    return v;
}
int go(int u, int v)
{
    return go(u, v, [](int, int) {});
}
void add(int u)
{
    bit.add(idx[u], 1);
}
}

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n - 1; ++i)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    scanf("%d", &m);
    for (int i = 0; i < m; ++i)
        scanf("%d%d", &u[i], &v[i]);
    hld::predfs(1, 1);
    hld::dfs(1, 1);
    for (int i = 0; i < m; ++i)
        lc[i] = hld::go(u[i], v[i]);
// for (int i = 0; i < m; ++i)
// printf("%d %d %d\n", u[i], v[i], lc[i]);
 // printf("结束了\n");
    for (int i = 0; i < m; ++i)
        edges[i] = {u[i], v[i], lc[i]};
    sort(edges, edges + m);
    vector<int> ans_list;
    for (int i = 0; i < m; ++i)
    {
        int x = 0;
        Edge &e = edges[i];
       // printf("%d %d %d\n", e.u, e.v, e.lca);
        hld::go(e.u, e.v, [&](int a, int b)
        {
            x += bit.query(b) - bit.query(a - 1);
        });
        cout << x << endl;
        if (x) continue;
        hld::add(e.lca);
        ans++;
        ans_list.push_back(e.lca);
    }
    //printf("答案:");
    cout << ans << endl;
   // printf("答案结束\n");
    for (int i = 0; i < ans; ++i)
        printf("%d%c", ans_list[i], i + 1 == ans ? '\n' : ' ');

}