BZOJ 1787: [Ahoi2008]Meet 紧急集合 LCA
1787: [Ahoi2008]Meet 紧急集合
Description
Input
Output
Sample 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
1 2
2 3
2 4
4 5
5 6
4 5 6
6 3 1
2 4 4
6 6 6
Sample Output
5 2
2 5
4 1
6 0
HINT
题解:求出两两lca,其中有两个相同,答案则为另一个,参考HZWer.
///1085422276 #include<bits/stdc++.h> using namespace std; //#pragma comment(linker, "/STACK:102400000,102400000") using namespace std ; typedef long long ll; #define mem(a) memset(a,0,sizeof(a)) #define pb push_back inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1;ch=getchar(); } while(ch>='0'&&ch<='9'){ x=x*10+ch-'0';ch=getchar(); }return x*f; } //**************************************** const int N=500500; #define mod 1000000007 #define inf 1000000007 int n,m,head[N],t,vis[N],deep[N],fa[N][20]; struct ss { int to,next; }e[N*2]; void add(int u,int v) { e[t].next=head[u];e[t].to=v;head[u]=t++; } void init() { t=1;mem(head);mem(vis);mem(fa);mem(deep); } void dfs(int x) { vis[x]=1; for (int i=1; i<=18 ;i++) { if(deep[x]<(1<<i)) break; fa[x][i] = fa[fa[x][i-1]][i-1]; } for (int i=head[x];i;i=e[i].next) { if(vis[e[i].to]) continue; deep[e[i].to]=deep[x]+1; fa[e[i].to][0]=x; dfs(e[i].to); } } int RMQ_LCA(int x,int y) { if(deep[x]<deep[y]) swap(x,y); int d=deep[x]-deep[y]; for (int i=0; i<=18 ;i++) if((1<<i)&d) x=fa[x][i]; for (int i=18; i>=0 ;i--) { if(fa[x][i]!=fa[y][i]) { x=fa[x][i];y=fa[y][i]; } } if(x==y) return x; else return fa[x][0]; } int Dis_LCA(int x,int y) { int LCA= RMQ_LCA(x,y); return (deep[x]+deep[y]-2*deep[LCA]); } int cal(int x,int y,int z) { int A; int L1=RMQ_LCA(x,y); int L2=RMQ_LCA(y,z); int L3=RMQ_LCA(x,z); if(L1==L2) { A=L3; } else if(L2==L3) { A=L1; } else A=L2; int anss=Dis_LCA(x,A)+Dis_LCA(y,A)+Dis_LCA(z,A); printf("%d %d\n",A,anss); //cout<<A<<" "<<anss<<endl; } int main() { scanf("%d%d",&n,&m); init(); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v);add(v,u); } dfs(1); for(int i=1;i<=m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); cal(a,b,c); } return 0; }