题解 P2971【[USACO10HOL]Cow Politics G】
作者:互联网
似乎是一个很简洁的新做法。
显然 \(k\) 个点集互不干扰,可以分开处理。
对于每个点集,首先取出两个点 \(u,v\) 作为最远的两个点(为表述方便下文称为直径),然后考虑向点集中加入点 \(w\) 的过程。我们计算出 \(d_1=\operatorname{dis}(u,v),d_2=\operatorname{dis}(u,w),d_3=\operatorname{dis}(v,w)\),则点集的直径为 \(\max\{d_1,d_2,d_3\}\)。判断出哪两个点是新的直径,然后在这个新的直径的基础上继续加点即可。
正确性的话,类似于正常的树的直径,到一个点距离最远的点一定是一条直径的端点。若新的点要作为直径端点,只能是到原来直径两端距离有一个比原来直径要长。
时间复杂度 \(\mathcal O(n\log n)\)。
// Problem: P2971 [USACO10HOL]Cow Politics G
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2971
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x,y,z) for(int x=(y);x<=(z);x++)
#define per(x,y,z) for(int x=(y);x>=(z);x--)
#define debug(format...) fprintf(stderr, format)
#define fileIO(s) do{freopen(s".in","r",stdin);freopen(s".out","w",stdout);}while(false)
using namespace std;
typedef long long ll;
const int N = 2e5+5;
int n, k, a[N], fa[N][19], dis[N], rt;
vector<int> d[N], e[N];
template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}
void dfs(int u) {
dis[u] = dis[fa[u][0]] + 1;
rep(i, 1, 18) fa[u][i] = fa[fa[u][i-1]][i-1];
for(int v : e[u]) dfs(v);
}
int LCA(int u, int v) {
if(dis[u] < dis[v]) swap(u, v);
per(i, 18, 0) if(dis[fa[u][i]] >= dis[v]) u = fa[u][i];
if(u == v) return u;
per(i, 18, 0) if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
return fa[u][0];
}
int dist(int u, int v) {
return dis[u] + dis[v] - 2 * dis[LCA(u, v)];
}
int main() {
scanf("%d%d", &n, &k);
rep(i, 1, n) {
scanf("%d%d", &a[i], &fa[i][0]);
if(!fa[i][0]) rt = i;
d[a[i]].push_back(i);
e[fa[i][0]].push_back(i);
}
dfs(rt);
rep(i, 1, k) {
int u = d[i][0], v = d[i][1], sz = d[i].size();
for(int j=2;j<sz;j++) {
int w = d[i][j];
int d1 = dist(u, v), d2 = dist(u, w), d3 = dist(v, w);
int diameter = max(d1, max(d2, d3));
int U = 0, V = 0;
if(d1 == diameter) U = u, V = v;
else if(d2 == diameter) U = u, V = w;
else U = v, V = w;
u = U; v = V;
}
printf("%d\n", dist(u, v));
}
return 0;
}
标签:USACO10HOL,int,题解,P2971,fa,直径,rep,dis 来源: https://www.cnblogs.com/ruierqwq/p/LG-P2971.html