BZOJ 1787: [Ahoi2008]Meet 紧急集合 LCA

1787: [Ahoi2008]Meet 紧急集合


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

题解:求出两两lca,其中有两个相同,答案则为另一个,参考HZWer.

///1085422276

#include<bits/stdc++.h>
using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std ;
typedef long long ll;
#define mem(a) memset(a,0,sizeof(a))
#define pb push_back
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-'0';ch=getchar();
    }return x*f;
}
//****************************************
const int  N=500500;
#define mod 1000000007
#define inf 1000000007
int n,m,head[N],t,vis[N],deep[N],fa[N][20];
struct ss {
  int to,next;
}e[N*2];
void add(int u,int v) {
   e[t].next=head[u];e[t].to=v;head[u]=t++;
}
void init() {
  t=1;mem(head);mem(vis);mem(fa);mem(deep);
}
void dfs(int x) {
    vis[x]=1;
    for (int i=1; i<=18 ;i++) {
        if(deep[x]<(1<<i)) break;
        fa[x][i] = fa[fa[x][i-1]][i-1];
    }
    for (int i=head[x];i;i=e[i].next) {
        if(vis[e[i].to]) continue;
        deep[e[i].to]=deep[x]+1;
        fa[e[i].to][0]=x;
        dfs(e[i].to);
    }
}
int RMQ_LCA(int x,int y) {
    if(deep[x]<deep[y]) swap(x,y);
    int d=deep[x]-deep[y];
    for (int i=0; i<=18 ;i++)
        if((1<<i)&d) x=fa[x][i];
    for (int i=18; i>=0 ;i--) {
        if(fa[x][i]!=fa[y][i]) {
            x=fa[x][i];y=fa[y][i];
        }
    }
    if(x==y) return x;
    else return fa[x][0];
}
int Dis_LCA(int x,int y) {
    int LCA= RMQ_LCA(x,y);
    return (deep[x]+deep[y]-2*deep[LCA]);
}
int cal(int x,int y,int z)  {
    int A;
    int L1=RMQ_LCA(x,y);
    int L2=RMQ_LCA(y,z);
    int L3=RMQ_LCA(x,z);
    if(L1==L2) {
        A=L3;
    }
    else if(L2==L3) {
        A=L1;
    }
    else A=L2;
    int anss=Dis_LCA(x,A)+Dis_LCA(y,A)+Dis_LCA(z,A);
    printf("%d %d\n",A,anss);
    //cout<<A<<" "<<anss<<endl;
}
int main() {
     scanf("%d%d",&n,&m);
     init();
     for(int i=1;i<n;i++) {
            int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
     }
     dfs(1);
     for(int i=1;i<=m;i++) {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        cal(a,b,c);
     }

   return 0;
}
代码

 

posted @ 2015-11-09 20:28  meekyan  阅读(216)  评论(0编辑  收藏  举报