BZOJ 1832: [AHOI2008]聚会|Lca

来源:互联网 发布:自学剑道软件 编辑:程序博客网 时间:2024/05/17 05:57

求出3个点两两的lca 有两个是相同的选另一个作为聚会地点
然后算距离 树剖求Lca似乎很快的样子

#include<set>#include<map>#include<ctime>#include<queue>#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#define T 500006#define MX 1e9using namespace std;int top[T],fa[T],deep[T],size[T];int head[T],lst[2*T],nxt[2*T];int n,m,tot;int sc(){    int i=0,f=1; char c=getchar();    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();    return i*f;}void insert(int x,int y){    lst[++tot]=y; nxt[tot]=head[x]; head[x]=tot;    lst[++tot]=x; nxt[tot]=head[y]; head[y]=tot;}void dfs(int x,int f){    deep[x]=deep[f]+1;size[x]=1;    for(int i=head[x];i;i=nxt[i])        if(lst[i]!=f)        {            fa[lst[i]]=x;            dfs(lst[i],x);            size[x]+=size[lst[i]];        }}void _dfs(int x,int htp){    int k=0;top[x]=htp;    for(int i=head[x];i;i=nxt[i])        if(lst[i]!=fa[x]&&size[lst[i]]>size[k])k=lst[i];    if(!k)return;_dfs(k,htp);    for(int i=head[x];i;i=nxt[i])        if(lst[i]!=fa[x]&&lst[i]!=k)            _dfs(lst[i],lst[i]);}int Lca(int x,int y){    while(top[x]!=top[y])    {        if(deep[top[x]]<deep[top[y]])swap(x,y);        x=fa[top[x]];    }    return deep[x]>deep[y]?y:x;}int main(){    n=sc(),m=sc();    for(int i=1;i<n;i++)    {        int x=sc(),y=sc();        insert(x,y);    }    dfs(1,0);    _dfs(1,1);    for(int i=1;i<=m;i++)    {        int x=sc(),y=sc(),z=sc(),sum,t;        int a=Lca(x,y),b=Lca(y,z),c=Lca(x,z);        if(b==c)t=a;else if(a==c)t=b;else t=c;        sum=deep[x]+deep[y]+deep[z]+3*deep[t]-2*(deep[Lca(x,t)]+deep[Lca(y,t)]+deep[Lca(z,t)]);        printf("%d %d\n",t,sum);    }    return 0;}
0 0
原创粉丝点击