洛谷 P4281 [AHOI2008] 紧急集合 题解

挺好的一道题,本身不难,就把求两个点的LCA变为求三个点两两求LCA,不重合的点才是最优解。值得一提的是,最后对答案的处理运用差分的思想:假设两点 一点深度为d1,另一点

深度为d2,它们LCA深度为d3,这二者之间的距离即为d1+d1-2*d3,只要将这两点推广成三点即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define maxn 500000
 6 using namespace std;
 7 inline int read() 
 8 {
 9     int x=0;
10     bool f=1;
11     char c=getchar();
12     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
13     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
14     if(f) return x;
15     return 0-x;
16 }
17 int n,m;
18 long long ans;
19 int f[maxn+10][25],dep[maxn+10],t;
20 struct node
21 {
22     int from,to,nex;
23 }edge[2*maxn+10];
24 int head[2*maxn+10],tot=0;
25 inline void add(int x,int y)
26 {
27     edge[++tot].from=x;
28     edge[tot].to=y;
29     edge[tot].nex=head[x];
30     head[x]=tot;
31 }
32 inline void Deal_first(int u,int father)
33 {
34     dep[u]=dep[father]+1;
35     for(int i=0;i<=19;i++)
36     {
37         f[u][i+1]=f[f[u][i]][i];
38     }
39     for(int e=head[u];e;e=edge[e].nex)
40     {
41         int v=edge[e].to;
42         if(v==father)continue;
43         f[v][0]=u;
44         Deal_first(v,u);
45     }
46 }
47 inline int LCA(int x,int y)
48 {
49     if(dep[x]<dep[y])swap(x,y);
50     for(int i=20;i>=0;i--)
51     {
52         if(dep[f[x][i]]>=dep[y])x=f[x][i];
53         if(x==y)return x;
54     }
55     for(int i=20;i>=0;i--)
56     {
57         if(f[x][i]!=f[y][i])
58         {
59             x=f[x][i];
60             y=f[y][i];
61         }
62     }
63     return f[x][0];
64 }
65 int main()
66 {
67     n=read();m=read();
68     for(int i=1;i<=n-1;i++)
69     {
70         int a,b;
71         a=read();b=read();
72         add(a,b);add(b,a);
73     }
74     Deal_first(1,0);
75     for(int i=1;i<=m;i++)
76     {
77         ans=0;
78         int a,b,c;
79         a=read();b=read();c=read();
80         int t1=LCA(a,b);
81         int t2=LCA(a,c);
82         int t3=LCA(b,c);
83         if(t1==t2)t=t3;
84         else if(t1==t3)t=t2;
85         else if(t2==t3)t=t1;
86         ans=dep[a]+dep[b]+dep[c]-dep[t1]-dep[t2]-dep[t3];
87         printf("%d %lld
",t,ans);
88     }
89     return 0;
90 }
请各位大佬斧正(反正我不认识斧正是什么意思)
原文地址:https://www.cnblogs.com/handsome-zyc/p/11237610.html