标签:
【思路】
Lca。
求出三点之间的lca,会出现两个点相同的情况,集合点为另外一个点。
【代码】
1 /************************************************************** 2 Problem: 1787 3 User: hahalidaxin2 4 Language: C++ 5 Result: Accepted 6 Time:3716 ms 7 Memory:65216 kb 8 ****************************************************************/ 9 10 #include<cstdio> 11 #include<cstring> 12 #include<queue> 13 #include<vector> 14 #include<iostream> 15 using namespace std; 16 17 const int maxn = 500000+10; 18 const int maxd = 19; 19 20 struct Edge{ int u,v; 21 }; 22 vector<int> G[maxn]; 23 vector<Edge> es; 24 25 int d[maxn]; 26 int p[maxn][maxd]; 27 28 void addedge(int u,int v) { 29 es.push_back((Edge){u,v}); 30 int m=es.size(); G[u].push_back(m-1); 31 } 32 void dfs(int u,int fa) { 33 for(int i=1;i<=maxd;i++) { //构造倍增数组 34 if(d[u]<(1<<i)) break; 35 p[u][i]=p[p[u][i-1]][i-1]; 36 } 37 for(int i=0;i<G[u].size();i++) { 38 Edge e=es[G[u][i]]; int v=e.v; 39 if(v!=fa) 40 d[v]=d[u]+1 , p[v][0]=u , dfs(v,u); 41 } 42 } 43 int lca(int u,int v) { 44 if(d[v]>d[u]) swap(u,v); 45 int dep=d[u]-d[v]; 46 for(int i=0;i<maxd;i++) 47 if((1<<i)&dep) u=p[u][i]; 48 if(u==v) return u; 49 for(int i=maxd-1;i>=0;i--) 50 if(p[u][i]!=p[v][i]) 51 u=p[u][i] , v=p[v][i]; 52 return p[u][0]; 53 } 54 int dist(int x,int y) { return d[x]+d[y]-(d[lca(x,y)]<<1); } 55 int n,m; 56 57 void read(int& x) { 58 char c=getchar(); 59 while(!isdigit(c)) c=getchar(); 60 x=0; 61 while(isdigit(c)) 62 x=x*10+c-‘0‘ , c=getchar(); 63 } 64 int main() { 65 read(n),read(m); 66 int u,v; 67 for(int i=0;i<n-1;i++) { 68 read(u),read(v); 69 addedge(u,v); addedge(v,u); 70 } 71 dfs(n>>1,-1); 72 int a,b,c,lab,lac,lbc,s; 73 while(m--) { 74 read(a),read(b),read(c); 75 lab=lca(a,b),lac=lca(a,c),lbc=lca(b,c); 76 if(lab==lac) s=lbc; 77 else if(lab==lbc) s=lac; 78 else s=lab; 79 printf("%d %d\n",s,dist(a,s)+dist(b,s)+dist(c,s)); 80 } 81 return 0; 82 }
bzoj 1787 [Ahoi2008]Meet 紧急集合(1832 [AHOI2008]聚会)
标签:
原文地址:http://www.cnblogs.com/lidaxin/p/5096732.html