1. 程式人生 > >[BZOJ1787] [Ahoi2008]Meet 緊急集合

[BZOJ1787] [Ahoi2008]Meet 緊急集合

return scrip while www tput markdown print examples bzoj

友鏈

Description


技術分享圖片

技術分享圖片

技術分享圖片

Examples


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 

output

5 2 
2 5 
4 1 
6 0 

Solution

兩兩算出LCA,有兩個LCA是相同的,選擇另一個作為答案

這道題似乎卡常數

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 500005

int head[MAXN];
int anc[20][MAXN],d[MAXN];
int
N,M; struct edge{ int v,next; }G[MAXN<<1]; inline int read(){ int num = 0;char ch = getchar(); while(ch<‘0‘||ch>‘9‘)ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘)num=num*10+ch-48,ch=getchar(); return num; } int tot = 0; inline void add(int u,int v){ G[++tot].v=v;G[tot].next=head[u];head[u]=tot; } inline
void dfs(int u,int fa){ for(register int i=head[u];i;i=G[i].next){ int v = G[i].v;if(v==fa)continue; d[v]=d[u]+1;anc[0][v]=u; dfs(v,u); } } inline void find_your_relative(){ for(register int i=1;i<=19;++i) for(register int j=1;j<=N;++j) anc[i][j] = anc[i-1
][anc[i-1][j]]; } inline int LCA(int u,int v){ if(d[u]<d[v])std::swap(u,v); for(register int i=19;i>=0;i--) if(d[anc[i][u]]>=d[v])u=anc[i][u]; if(u==v)return u; for(register int i=19;i>=0;i--) if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v]; return anc[0][u]; } inline int dis(int u,int v){ int lca = LCA(u,v); return d[u]+d[v]-(d[lca]<<1); } int main(){ N=read();M=read(); int u,v,a; for(register int i=1;i<N;++i){ u=read();v=read(); add(u,v);add(v,u); } d[1]=1;anc[0][1]=0; dfs(1,0); find_your_relative(); for(register int i=1;i<=M;++i){ u=read();v=read();a=read(); int lca_uv = LCA(u,v); int lca_ua = LCA(u,a); int lca_va = LCA(v,a); if(lca_uv==lca_ua)printf("%d %d\n",lca_va,d[v]+d[a]-(d[lca_va]<<1)+dis(lca_va,u)); else if(lca_uv==lca_va)printf("%d %d\n",lca_ua,d[u]+d[a]-(d[lca_ua]<<1)+dis(lca_ua,v)); else if(lca_ua==lca_va)printf("%d %d\n",lca_uv,d[v]+d[u]-(d[lca_uv]<<1)+dis(lca_uv,a)); } return 0; }

[BZOJ1787] [Ahoi2008]Meet 緊急集合