模板copy from http://codeforces.com/contest/832/submission/28835143
题意,给出一棵有n个结点的树,再给出其中的三个结点 s,t,f ,求路径 (s,t) (s,f) (t,f) 三者的最大公共结点数
对于(t,f) (s,f)的公共结点数,有
懒得细想了,暴力对s,t,f生成排列(反正一共仨数,最多也就3!=6个排列),求各种情况下的最大ans
#include<bits/stdc++.h> using namespace std; const int N=1e5+8; const int DEG=17; //int time_tag,in[N],out[N],dep[N]; int dep[N]; int fa[N][DEG]; int n,q; vector<int> e[N]; void dfs(int u) { // in[u]=++time_tag; for(int i=1;i<DEG;i++) fa[u][i]=fa[fa[u][i-1]][i-1]; for(int i=0;i<e[u].size();i++) { int v=e[u][i]; dep[v]=dep[u]+1; fa[v][0]=u; dfs(v); } // out[u]=time_tag; } int lca(int u,int v) { if(dep[u]<dep[v]) swap(u,v); for(int i=0,d=dep[u]-dep[v];d;i++,d>>=1) if(d&1) u=fa[u][i]; if(u==v) return u; for(int i=DEG-1;i>=0;i--) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i]; return fa[u][0]; } int dis(int u,int v) { return dep[u]+dep[v]-2*dep[lca(u,v)]; } int main() { scanf("%d%d",&n,&q); for(int i=2;i<=n;i++) { int p; scanf("%d",&p); e[p].push_back(i); } dfs(1); while(q--) { int k[3]; for(int i=0;i<3;i++) scanf("%d",&k[i]); sort(k,k+3); int ans=0; do { ans=max(ans,(dis(k[0],k[1])+dis(k[0],k[2])-dis(k[1],k[2]))/2); }while(next_permutation(k,k+3)); printf("%d ",ans+1); } }
//当时其实想到了ans的表达式,但是不会LCA,不自信是否把题读准确了(前边读题出的问题很大。。),所以直接放弃了这道题。。然而事后发现这题没读错,算法也没错。。。如果直接从网上copy一份求树上两点距离的板子,这题还是可以过的——一只弱鸡的懊悔