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 }