luogu P4281 [AHOI2008]紧急集合 / 聚会
这道题第一眼看
就
LCA啊
三个点,两两求LCA,一定有两个是相同的
另一个点一定深度最小,所以更优
用一个depth数组记录每个点的深度,加加减减就得出来了
emmmm
很简单
(gg布置的另两道题,一道LCA板子不用说,另一道也是板子,就多了加加减减
(这道虽然是紫题但也挺水的
#include<cstdio> #include<cmath> #include<algorithm> #define sev en using namespace std; #define N 500010 struct edgee{ int nxt,to; }edge[N << 1]; int head[N]; int depth[N]; int fa[N][31]; int cnt; void add(int x,int y){ edge[++cnt].to = y; edge[cnt].nxt = head[x]; head[x] = cnt; } void dfs(int x,int now){ depth[x] = now; for(int i = head[x];i;i = edge[i].nxt){ int v = edge[i].to; if(!depth[v]){ fa[v][0] = x; dfs(v,now + 1); } } } int LCA(int a,int b){ if(depth[a] < depth[b]) swap(a,b); for(int j = 30;j >= 0;j--) if(depth[a] - (1<<j) >= depth[b]) a = fa[a][j]; if(a != b){ for(int j = 30;j >= 0;j--){ if(fa[a][j] != fa[b][j]){ a = fa[a][j]; b = fa[b][j]; } } a = fa[a][0]; } return a; } int main(){ int n,m; scanf("%d%d",&n,&m); for(int i = 1;i < n;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs(1,0); for(int j = 1;j < 30;j++) for(int i = 1;i <= n;i++) fa[i][j] = fa[fa[i][j - 1]][j - 1]; for(int i = 1;i <= m;i++){ long long ans = 0; int rt; int a,b,c; scanf("%d%d%d",&a,&b,&c); int rt1 = LCA(a,b); int rt2 = LCA(b,c); int rt3 = LCA(a,c); if(rt1 == rt2) rt = rt3; else if(rt2 == rt3) rt = rt1; else if(rt1 == rt3) rt = rt2; ans = depth[a] + depth[b] + depth[c] - depth[rt1] - depth[rt2] - depth[rt3]; printf("%d %lld\n",rt,ans); } return 0; }
end.
(这题解写的也好水嘤嘤嘤