MMSet2
思路
这道题目显然能够通过的复杂度来暴力,这显然不能达到题目要求的复杂度,因此我们可以对题目要求我们计算的东西进行转换。
某个点到所有点集的最大距离最小,这就有点像是重心的求法了,但是这题又有所不同,如果这是在一颗树上,显然我们可以很快的得到答案,,所以这题我们也可以转换思想,每次求解得到点集中两点之间最长的距离,然后再对他向上取整。
问题转换为求解点集中得直径了,所以我们可以找到点集中的深度最大的点,然后通过这个点去求得点集的直径。
代码(事实证明树剖求lca是真的快)
/* Author : lifehappy */ #pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc++.h> #define mp make_pair #define pb push_back #define endl '\n' #define mid (l + r >> 1) #define lson rt << 1, l, mid #define rson rt << 1 | 1, mid + 1, r #define ls rt << 1 #define rs rt << 1 | 1 using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const double pi = acos(-1.0); const double eps = 1e-7; const int inf = 0x3f3f3f3f; inline ll read() { ll f = 1, x = 0; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); } return f * x; } const int N = 3e5 + 10; int head[N], to[N << 1], nex[N << 1], cnt = 1; int dep[N], son[N], sz[N], fa[N], top[N], tot; void dfs1(int rt, int f) { dep[rt] = dep[f] + 1; sz[rt] = 1, fa[rt] = f; for(int i = head[rt]; i; i = nex[i]) { if(to[i] == f) continue; dfs1(to[i], rt); if(!son[rt] || sz[to[i]] > sz[son[rt]]) son[rt] = to[i]; sz[rt] += sz[to[i]]; } } void dfs2(int rt, int t) { top[rt] = t; if(!son[rt]) return ; dfs2(son[rt], t); for(int i = head[rt]; i; i = nex[i]) { if(to[i] == fa[rt] || to[i] == son[rt]) continue; dfs2(to[i], to[i]); } } int lca(int x, int y) { while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x, y); x = fa[top[x]]; } return dep[x] < dep[y] ? x : y; } int dis(int x, int y) { return dep[x] + dep[y] - 2 * dep[lca(x, y)]; } void add(int x, int y) { to[cnt] = y; nex[cnt] = head[x]; head[x] = cnt++; } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int n = read(); for(int i = 1; i < n; i++) { int x = read(), y = read(); add(x, y); add(y, x); } dfs1(1, 0); dfs2(1, 1); int Q = read(); for(int i = 1; i <= Q; i++) { int m = read(); vector<int> a; int u = 0; for(int j = 1; j <= m; j++) { int x = read(); if(dep[x] > dep[u]) u = x; a.pb(x); } int ans = 0; for(int v : a) { if(v == u) continue; ans = max(ans, dis(u, v)); } printf("%d\n", (ans + 1) >> 1); } return 0; }