颓废了2个晚上,总算水掉了这道题……
这题我们使用倍增LCA可以解决。
每次三个点找两点间LCA,相同的LCA取另一个就可以了。
我没有使用读入优化,如果用了速度会更快吧……
#include<cstdio>
int n,m,h[500005],en,fa[500005][20],deep[500005],flg[500005];
struct Edge{
int b,next;
}e[1000005];
void add(int sa,int sb){
e[++en].b=sb;
e[en].next=h[sa];
h[sa]=en;
}
void Yuchuli(int u){
flg[u]=1;
for(int i=h[u];i;i=e[i].next){
int v=e[i].b;
if(!flg[v]){
deep[v]=deep[u]+1;
fa[v][0]=u;
Yuchuli(v);
}
}
}
void Move(int &u,int H){
for(int i=18;i>=0;i--){
if(deep[fa[u][i]]>=H){
u=fa[u][i];
}
}
}
int LCA(int u,int v){
int now=0;
if(deep[u]!=deep[v]){if(deep[u]>deep[v])Move(u,deep[v]);else Move(v,deep[u]);}
if(u==v){return u;}
for(int i=18;i>=0;i--){
if(fa[u][i]!=fa[v][i]){
u=fa[u][i];
v=fa[v][i];
}
}
return fa[u][0];
}
int GetCost(int u,int v){
int w=LCA(u,v);
return deep[u]+deep[v]-2*deep[w];
}
int main(){
freopen("1787.in","r",stdin);
freopen("1787.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<n;i++){
int sa,sb;
scanf("%d %d",&sa,&sb);
add(sa,sb);
add(sb,sa);
}
Yuchuli(1);
fa[1][0]=1;
for(int j=1;j<=18;j++){
for(int i=1;i<=n;i++){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
while(m--){
int sa,sb,sc;
scanf("%d %d %d",&sa,&sb,&sc);
int FineLCA,LCA1=LCA(sa,sb),LCA2=LCA(sa,sc),LCA3=LCA(sb,sc);
if(LCA1==LCA2)FineLCA=LCA3;
else if(LCA3==LCA2)FineLCA=LCA1;
else FineLCA=LCA2;
printf("%d %d\n",FineLCA,GetCost(FineLCA,sa)+GetCost(FineLCA,sb)+GetCost(FineLCA,sc));
}
return 0;
}
upd 2016.6.2
今天学习了Tarjan求LCA,用这个题练习一下
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=500005,INF=2100000000;
int n,m,h[N],en,f[N],vis[N],dep[N],anc[N];
struct Edge{
int b,next;
}e[N<<1];
struct List{
int v,par;
List *next;
List(){next=NULL;par=0;}
List(int _v,List *_next){v=_v;next=_next;par=0;}
}*Lis[N];
List *AddList(int u,int v){
List *node=new List(v,Lis[u]);
Lis[u]=node;
return node;
}
struct Query{
int u,v,w;
List *id11,*id12,*id21,*id22,*id31,*id32;
Query(){}
Query(int _u,int _v,int _w){u=_u;v=_v;w=_w;}
}Que[N];
void AddEdge(int sa,int sb){
e[++en].b=sb;
e[en].next=h[sa];
h[sa]=en;
}
int Find(int x){return x==f[x]?x:f[x]=Find(f[x]);}
int Abs(int x){return x>0?x:-x;}
int GetCost(int u,int v,int w){return dep[u]+dep[v]-2*dep[w];}
void Tarjan(int u,int fa){
f[u]=u;
dep[u]=dep[fa]+1;
for(int i=h[u];i;i=e[i].next){
int v=e[i].b;
if(!f[v]){Tarjan(v,u);f[v]=u;}
}
for(List *I=Lis[u];I;I=I->next){
int v=I->v;
if(f[v])I->par=Find(v);
}
}
int main(){
freopen("1787.in","r",stdin);
freopen("1787.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<n;i++){
int u,v;
scanf("%d %d",&u,&v);
AddEdge(u,v);AddEdge(v,u);
}
for(int i=1;i<=m;i++){
scanf("%d %d %d",&Que[i].u,&Que[i].v,&Que[i].w);
Que[i].id11=AddList(Que[i].u,Que[i].v);
Que[i].id21=AddList(Que[i].u,Que[i].w);
Que[i].id31=AddList(Que[i].v,Que[i].w);
Que[i].id12=AddList(Que[i].v,Que[i].u);
Que[i].id22=AddList(Que[i].w,Que[i].u);
Que[i].id32=AddList(Que[i].w,Que[i].v);
}
Tarjan(1,1);
for(int i=1;i<=m;i++){
int LCA1=max(Que[i].id11->par,Que[i].id12->par);
int LCA2=max(Que[i].id21->par,Que[i].id22->par);
int LCA3=max(Que[i].id31->par,Que[i].id32->par);
int Cost=GetCost(LCA1,Que[i].u,LCA1)+GetCost(LCA1,Que[i].v,LCA1)+GetCost(LCA1,Que[i].w,LCA2);
if(LCA1==LCA2){Cost=GetCost(LCA3,Que[i].u,LCA2)+GetCost(LCA3,Que[i].v,LCA3)+GetCost(LCA3,Que[i].w,LCA3);LCA1=LCA3;}
else if(LCA1==LCA3){Cost=GetCost(LCA2,Que[i].u,LCA2)+GetCost(LCA2,Que[i].v,LCA1)+GetCost(LCA2,Que[i].w,LCA2);LCA1=LCA2;}
printf("%d %d\n",LCA1,Cost);
}
return 0;
}