【BZOJ 1832】【AHOI 2008】聚会 &【BZOJ 1787】Meet 紧急集合

来源:互联网 发布:matlab计算矩阵编程 编辑:程序博客网 时间:2024/05/29 07:27

Description

给出一颗树,求点X使点x,y,z到它的距离最短,并求出来。

Solution

先把x,y,z的两两LCA求出来,
可以证明一定至少会有两个LCA使一样的,而X点就是与其他两个不同的那个,
于是就可以乱搞一波,
(本来想偷懒,结果WA了…QAQ)
复杂度:O(mlog2(n))

Code

#include<cstdio>#include<cstdlib>#define fo(i,a,b) for(int i=a;i<=b;i++)#define efo(i,q) for(int i=A[q];i;i=B[i][0]) #define iffa if(B[i][1]!=fa)using namespace std;const int N=500500,M=20;int read(int &n){    char ch=' ';int q=0,w=1;    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());    if(ch=='-')w=-1,ch=getchar();    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;}int n,m,ans,ans1;int ac[N];int g[N][M+1];int A[N],B[2*N][2],B0;void link(int q,int w){    B[++B0][0]=A[q],A[q]=B0,B[B0][1]=w;    B[++B0][0]=A[w],A[w]=B0,B[B0][1]=q;}void dfs(int q,int fa,int e){    g[q][0]=fa;ac[q]=e;    efo(i,q)iffa dfs(B[i][1],q,e+1);}int LCA1(int q,int w){    while(ac[q]>w)    {        int i=0;        while(ac[g[q][i+1]]>=w)i++;        q=g[q][i];    }    return q;}int LCA(int q,int w){    while(q!=w)    {        int i=0;        while(g[q][i+1]!=g[w][i+1])i++;        q=g[q][i];w=g[w][i];    }    return q;}int lca(int q,int w){    q=LCA1(q,ac[w]);w=LCA1(w,ac[q]);    return LCA(q,w);}int main(){    int q,w,e,m_;    read(n),read(m_);    fo(i,1,n-1)read(q),read(w),link(q,w);    dfs(1,0,1);    fo(j,1,M)fo(i,1,n)g[i][j]=g[g[i][j-1]][j-1];    while(m_--)    {        read(q),read(w),read(e);        int t=lca(q,w),t1=lca(w,e),t2=lca(q,e);        if(t==t1)ans=t2,ans1=ac[q]+ac[e]-ac[t2]+ac[w]-2*ac[t];            else if(t==t2)ans=t1,ans1=ac[w]+ac[e]-ac[t1]+ac[q]-2*ac[t];                else ans=t,ans1=ac[w]+ac[q]-ac[t]+ac[e]-2*ac[t1];        printf("%d %d\n",ans,ans1);    }    return 0;}
0 0
原创粉丝点击