luoguP4281[AHOI2008]紧急集合 / 聚会
最近复习lca,布置的三道题中最后一道就是这个紫题。当时看到是紫题吓了一跳(果然是我太弱了QAQ)然后仔细读了几遍题,发现这就是普通的lca嘛 (太水了) 其中变化的只有要分别求三者的lca。
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> using namespace std; typedef long long ll; struct kh{ int t, nxt; }e[2*500001]; int dep[500001], f[500001][22], tot, head[500001], lo[500001], t; ll ans = 0; void add(int x,int y) { e[++tot].t = y; e[tot].nxt = head[x]; head[x] = tot; } void dfs(int fa, int h) { dep[fa] = dep[h] + 1; f[fa][0] = h; for(int i = 1;(1<<i) <= dep[fa];i++) f[fa][i] = f[f[fa][i-1]][i-1]; for(int i = head[fa];i;i = e[i].nxt) if(e[i].t != h) dfs(e[i].t,fa); } int lca(int x,int y) { if(dep[x] < dep[y]) swap(x,y); while(dep[x] > dep[y]) x = f[x][lo[dep[x] - dep[y]] - 1]; if(x == y) return x; for(int k= lo[dep[x]] - 1;k >= 0;k--) if(f[x][k] != f[y][k]) x = f[x][k], y = f[y][k]; return f[x][0]; } int n, m, s, x, y, a, b, c; int main() { scanf("%d %d", &n, &m); for(int i = 1;i <= n - 1;i++) { scanf("%d %d", &a, &b); add(a, b); add(b, a); } dfs(1,0); for(int i = 1;i <= n;i++) lo[i] = lo[i - 1] + (1<<lo[i - 1] == i); for(int i = 1;i <= m;i++) { ans = 0; scanf("%d %d %d", &a, &b, &c); int t1 = lca(a,b);//分别求三者lca int t2 = lca(a,c); int t3 = lca(b,c); if(t1 == t2) t = t3; else if(t1 == t3) t = t2; else if(t2 == t3) t = t1; ans = dep[a] + dep[b] + dep[c] - dep[t1] - dep[t2] - dep[t3]; printf("%d %lld\n", t, ans); } return 0; }