P4281 [AHOI2008]紧急集合 / 聚会

原题链接

考察:LCA

思路:

        md想到了两两求lca但是没敢继续想下去...我是sb

        最近公共祖先一定是对u,v来说最近的,但是对于第三个点需要两两枚举求最小值.

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <queue>
 5 using namespace std;//2^19
 6 typedef long long LL;
 7 const LL INF = 1e18;
 8 const int N = 500010,P = 19;
 9 int h[N],idx,n,m,depth[N],fa[N][20];
10 struct Road{
11     int fr,to,ne;
12 }road[N<<1];
13 void add(int a,int b)
14 {
15     road[idx].fr = a,road[idx].to = b,road[idx].ne = h[a],h[a] = idx++;
16 }
17 void bfs(int s)
18 {
19     queue<int> q;
20     memset(depth,0x3f,sizeof depth);
21     depth[s] = 1,depth[0] = 0;
22     q.push(s);
23     while(q.size())
24     {
25         int u = q.front();
26         q.pop();
27         for(int i=h[u];~i;i=road[i].ne)
28         {
29             int v = road[i].to;
30             if(depth[v]>depth[u]+1)
31             {
32                 depth[v] = depth[u]+1;
33                 q.push(v);
34                 fa[v][0] = u;
35                 for(int j=1;j<=19;j++)
36                  fa[v][j] = fa[fa[v][j-1]][j-1];
37             }
38         }
39     }
40 }
41 int lca(int a,int b)
42 {
43     if(depth[a]<depth[b]) swap(a,b);
44     for(int j=19;j>=0;j--)
45       if(depth[fa[a][j]]>=depth[b]) a = fa[a][j];
46     if(a==b) return a;
47     for(int j=19;j>=0;j--)
48       if(fa[a][j]!=fa[b][j]) a = fa[a][j],b = fa[b][j];
49     return fa[a][0];
50 }
51 LL get(int a,int b,int c)
52 {
53     int d = lca(a,b);
54     LL dist = depth[a]-depth[d];
55     dist+=depth[b]-depth[d];
56     int anc = lca(c,d);
57     dist+=depth[c]+depth[d]-depth[anc]*2;
58     return dist;
59 }
60 int main() 
61 {
62     scanf("%d%d",&n,&m);
63     memset(h,-1,sizeof h);
64     for(int i=1;i<n;i++)
65     {
66         int a,b; scanf("%d%d",&a,&b);
67         add(a,b); add(b,a);
68     }
69     bfs(1);
70     while(m--) 
71     {
72         int a,b,c; scanf("%d%d%d",&a,&b,&c);
73         LL ans = INF; int anc;
74         LL d1 = get(a,b,c),d2 = get(b,c,a),d3 = get(a,c,b);
75         if(d1<ans) ans = d1,anc = lca(a,b);
76         if(d2<ans) ans = d2,anc = lca(b,c);
77         if(d3<ans) ans = d3,anc = lca(a,c);
78         printf("%d %lld\n",anc,ans);
79     }
80     return 0;
81 }

 

posted @ 2021-05-11 21:02  acmloser  阅读(48)  评论(0编辑  收藏  举报