10
13
2015
0

[BZOJ1787&1832] [AHOI2008] Meet 紧急集合 && 聚会

颓废了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;
}
Category: BZOJ | Tags: OI bzoj | Read Count: 483

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com