并查集板子题。
对于并查集而言,很难进行删边操作,因此考虑将删边反过来,改为符合题意就加边。
由题意,同在 中的点不能相连,所以可以在并查集的合并过程中手动保持让
中的点作为并查集的根(同一个集合中最多有一个
中的点)。然后连边时,若两边的点(根)均为
中的点,则不连接,计入答案;否则连边,让
中的点(若存在)为根。
代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, m;
cin >> n >> m;
vector<int> u(n + 7), v(n + 7), vis(n + 7), fa(n + 7);
for (int i = 1; i <= n; i++)
fa[i] = i;
for (int i = 1; i < n; i++)
cin >> u[i] >> v[i];
for (int i = 1; i <= m; i++)
{
int k;
cin >> k;
vis[k] = 1;
}
function<int(int)> find = [&](int x) -> int
{
if (fa[x] == x)
return x;
return fa[x] = find(fa[x]);
};
using Pr = pair<int, int>;
int ans = 0;
vector<Pr> ans_;
for (int i = 1; i < n; i++)
{
int ru = find(u[i]), rv = find(v[i]);
if (ru == rv)
continue;
if (vis[ru] && vis[rv])
{
ans++;
ans_.push_back(Pr(u[i], v[i]));
continue;
}
if (vis[ru])
fa[rv] = ru;
else
fa[ru] = rv;
}
cout << ans << '\n';
for (auto [x, y] : ans_)
{
cout << x << ' ' << y << '\n';
}
return 0;
}

京公网安备 11010502036488号