rt,计算答案的思路是分三类
在虚树上的圆点,如果子树内和子树外都有关键点,那么计入答案。
不在虚树上的圆点,如果需要计入答案那么一定会在虚树上两个点中间,计算一类点时加上 dist(u)−dist(fa)
在虚树上的圆点,有超过一个儿子的 siz >= 1,计入答案。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 4e5 + 5;
int n, m;
int tot;
vector<int> e[N], G[N], E[N];
int p[N], a[N];
int dfn[N], low[N], tim;
stack<int> stk;
int dep[N], fa[N][20], dist[N];
int dfnG[N], timG;
int siz[N], key[N];
int ans;
void tarjan(int u) {
dfn[u] = low[u] = ++ tim;
stk.push(u);
for (auto v : e[u]) {
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
if (low[v] >= dfn[u]) {
tot ++;
int x;
do {
x = stk.top(), stk.pop();
G[x].push_back(tot);
G[tot].push_back(x);
} while (x != v);
G[u].push_back(tot);
G[tot].push_back(u);
}
}
else {
low[u] = min(low[u], dfn[v]);
}
}
}
void dfs(int u, int fath) {
dfnG[u] = ++ timG;
dep[u] = dep[fath] + 1, dist[u] = dist[fath] + (u <= n);
fa[u][0] = fath;
for (int i = 1; i <= __lg(dep[u]); i ++) {
fa[u][i] = fa[fa[u][i - 1]][i - 1];
}
for (auto v : G[u]) {
if (v == fath) continue;
dfs(v, u);
}
}
int lca(int u, int v) {
if (dep[u] < dep[v]) {
swap(u, v);
}
while (dep[u] != dep[v]) {
u = fa[u][__lg(dep[u] - dep[v])];
}
if (u == v) {
return u;
}
for (int k = __lg(dep[u]); k >= 0; k --) {
if (fa[u][k] != fa[v][k]) {
u = fa[u][k], v = fa[v][k];
}
}
return fa[u][0];
}
bool cmp(int a, int b) {
return dfnG[a] < dfnG[b];
}
void dfs_E(int u, int sum) {
siz[u] = key[u];
int c = 0;
for (auto v : E[u]) {
dfs_E(v, sum);
siz[u] += siz[v];
if (siz[v] >= 1) {
c ++;
}
}
for (auto v : E[u]) {
if (siz[v] >= 1 && sum - siz[v] >= 1) {
ans += dist[fa[v][0]] - dist[u];
}
}
E[u].clear();
if (key[u] || u > n) {
return;
}
if ((sum - siz[u] >= 1 && siz[u] >= 1) || c > 1) {
ans ++;
}
}
void solve() {
memset(dfn, 0, sizeof dfn);
memset(low, 0, sizeof low);
memset(dfnG, 0, sizeof dfnG);
memset(dist, 0, sizeof dist);
cin >> n >> m;
for (int i = 1; i <= 2 * n; i ++) {
e[i].clear(), G[i].clear(), E[i].clear();
}
for (int i = 1; i <= m; i ++) {
int u, v;
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
tot = n;
tarjan(1), dfs(1, 0);
int q;
cin >> q;
while (q --) {
int c;
cin >> c;
int cnt = 0;
for (int i = 1; i <= c; i ++) {
cin >> p[i];
key[p[i]] = 1;
a[++ cnt] = p[i];
}
a[++ cnt] = 1;
sort(p + 1, p + 1 + c, cmp);
for (int i = 1; i < c; i ++) {
a[++ cnt] = lca(p[i], p[i + 1]);
}
sort(a + 1, a + 1 + cnt, cmp);
cnt = unique(a + 1, a + 1 + cnt) - a - 1;
// cout << "----------\n";
for (int i = 1; i < cnt; i ++) {
E[lca(a[i], a[i + 1])].push_back(a[i + 1]);
// cout << lca(a[i], a[i + 1]) << " " << a[i + 1] << "\n";
}
ans = 0;
dfs_E(1, c);
cout << ans << "\n";
for (int i = 1; i <= c; i ++) {
key[p[i]] = 0;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
int t;
cin >> t;
while (t --) {
solve();
}
return 0;
}