1. 程式人生 > >BZOJ——1787: [Ahoi2008]Meet 緊急集合

BZOJ——1787: [Ahoi2008]Meet 緊急集合

size image mes img clas algorithm meet nss spa

http://www.lydsy.com/JudgeOnline/problem.php?id=1787

題目描述

技術分享

輸入

技術分享

輸出

技術分享

樣例輸入

6 4
1 2
2 3
2 4
4 5
5 6
4 5 6
6 3 1
2 4 4
6 6 6

樣例輸出


5 2
2 5
4 1
6 0

提示

技術分享

易發現:三個點兩兩求出LCA,一定至少有兩個LCA相等

    若只有兩個相等,那聚集點就是剩下的LCA

    若三個相等,那聚集點就是LCA

 1 #include <algorithm>
 2
#include <cstdio> 3 #include <vector> 4 5 using namespace std; 6 7 const int N(1e5*5+15); 8 vector<int>vec[N]; 9 int n,m,x,y,z; 10 int anspoint,anssum; 11 int deep[N],dad[N],size[N],top[N]; 12 13 void DFS(int x) 14 { 15 size[x]=1; deep[x]=deep[dad[x]]+1;
16 for(int i=0;i<vec[x].size();i++) 17 if(dad[x]!=vec[x][i]) 18 { 19 dad[vec[x][i]]=x; 20 DFS(vec[x][i]); 21 size[x]+=size[vec[x][i]]; 22 } 23 } 24 25 void DFS_(int x) 26 { 27 int t=0; if(!top[x]) top[x]=x; 28 for(int
i=0;i<vec[x].size();i++) 29 if(vec[x][i]!=dad[x]&&size[t]<size[vec[x][i]]) t=vec[x][i]; 30 if(t) top[t]=top[x],DFS_(t); 31 for(int i=0;i<vec[x].size();i++) 32 if(vec[x][i]!=dad[x]&&t!=vec[x][i]) DFS_(vec[x][i]); 33 } 34 35 int LCA(int x,int y) 36 { 37 while(top[x]!=top[y]) 38 { 39 if(deep[top[x]]<deep[top[y]]) swap(x,y); 40 x=dad[top[x]]; 41 } 42 if(deep[x]>deep[y]) swap(x,y); 43 return x; 44 } 45 46 int main() 47 { 48 scanf("%d%d",&n,&m); 49 for(int i=1;i<n;i++) 50 { 51 scanf("%d%d",&x,&y); 52 vec[x].push_back(y); 53 vec[y].push_back(x); 54 } 55 DFS(1); DFS_(1); 56 for(;m;m--) 57 { 58 scanf("%d%d%d",&x,&y,&z); 59 anspoint=LCA(x,y)^LCA(x,z)^LCA(y,z); 60 anssum =deep[x]+deep[anspoint]-(deep[LCA(x,anspoint)]<<1); 61 anssum+=deep[y]+deep[anspoint]-(deep[LCA(y,anspoint)]<<1); 62 anssum+=deep[z]+deep[anspoint]-(deep[LCA(z,anspoint)]<<1); 63 printf("%d %d\n",anspoint,anssum); 64 } 65 return 0; 66 }

BZOJ——1787: [Ahoi2008]Meet 緊急集合