BZOJ 1787 紧急集合
1787: [Ahoi2008]Meet 紧急集合
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1220 Solved: 500
[Submit][Status]
Description
Input
Output
Sample Input
6 4
1 2
2 3
2 4
4 5
5 6
4 5 6
6 3 1
2 4 4
6 6 6
Sample Output
5 2
2 5
4 1
6 0
HINT
——分割线——
卧槽、、感觉好不好QAQ我写的程序最近总是评测CE!这、、让我怎么去考NOIP!好吧,这次是因为用了IO库里的一个Swap函数,可是明明在IO库里啊、、、为什么会CE、、看来我以后不能提前写好多好多头文件了、、、、
言归正传,这题就是练一下LCA,卧槽,这次我感受到了数组地址冲突导致的莫名其妙数据不正常问题,调了好久才发现是地址冲突QAQ!LCA感觉还是不是很熟练,找时间再写一题,这道题吧,很容易得到,他们的集合点就是三个点两两的LCA之一,都算出来比一下距离就好啦~
代码:
/*Author:WNJXYK*/ #include<cstdio> using namespace std; #define LL long long const int Maxn=500000; int n,m; struct Node{ int u; int nxt; Node(){} Node(int a,int b){ u=a; nxt=b; } }; int nume=0; Node link[2*Maxn+10]; int links[Maxn+10]; int visited[Maxn+10]; int lca[Maxn+10][20]; int depth[Maxn+10]; int Mlca=20; int dfs(int x,int deep){ depth[x]=deep; visited[x]=true; for(int i=1;i<Mlca;i++){ lca[x][i]=lca[lca[x][i-1]][i-1]; } for (int i=links[x];i;i=link[i].nxt){ int point=link[i].u; if (!visited[point]){ lca[point][0]=x; dfs(point,deep+1); } } } inline void swin(int &x,int step){ for (int i=0;step>0;i++){ if (step%2==1) x=lca[x][i]; step/=2; } } inline void swap(int &x,int &y){ x=x+y; y=x-y; x=x-y; } inline int LCA(int x,int y){ if (depth[x]>depth[y]) swap(x,y); swin(y,depth[y]-depth[x]); if (x==y) return x; for (int i=0;;){ for(i=0;lca[x][i]!=lca[y][i];i++); if (i==0) return lca[x][i]; x=lca[x][i-1]; y=lca[y][i-1]; } return -1; } inline void addEdge(int x,int y){ link[++nume]=Node(y,links[x]); links[x]=nume; } inline int dist(int x,int y){ int l=LCA(x,y); return depth[x]+depth[y]-2*depth[l]; } int main(){ scanf("%d%d",&n,&m); for (int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); addEdge(x,y); addEdge(y,x); } lca[1][0]=1; dfs(1,1); for (int i=1;i<=m;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); int lx,ly,lz; lx=LCA(x,y); ly=LCA(y,z); lz=LCA(z,x); //cout<<lx<<" "<<ly<<" "<<lz<<" "<<endl; int l=lx^ly^lz; int ans=dist(l,x)+dist(l,y)+dist(l,z); printf("%d %d\n",l,ans); } return 0; }