NC13950 Alliances(LCA)
对于每个帮派求他们的lca,对于每个询问,先将所含的所有帮派求lca,将这个和当前首都比较,如果首都不在最高点的lca的子树当中,那么他的答案就是这个最高点lca和首都的距离
如果在这个子树下,那么只需要求取dfs序在首都前后的两个点求一个min即可。
分析这道题目,我们想到lca的原因是,这里有树上两点的距离的判定,这种题,很多情况下都是lca来做,但是因为题目中有很多点,因此我们要缩减计算的次数。通过思考,我们发现对于可以分成两种情况讨论。而对于子树中的情况,其实不难想到dfs序+二分查找,因为前后总是最近的,其他的点没有意义。有个点是因为两个城市之间的所有城市都是特殊点,因此,求得前后点后,还要进一步转化。这个转化比较明显,可以通过观察获得。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+10; const int mod=1e9+7; int h[N],ne[N],e[N],idx; int dfn[N],times; int f[N][35]; int depth[N]; vector<int> num[N]; int p[N]; int id[N]; int sz[N]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void dfs(int u,int fa){ depth[u]=depth[fa]+1; f[u][0]=fa; dfn[u]=++times; id[times]=u; int i; for(i=1;i<=30;i++){ f[u][i]=f[f[u][i-1]][i-1]; } for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; dfs(j,u); } } int lca(int a,int b){ if(depth[a]<depth[b]) swap(a,b); int i; for(i=30;i>=0;i--){ if(depth[f[a][i]]>=depth[b]){ a=f[a][i]; } } if(a==b) return a; for(i=30;i>=0;i--){ if(f[a][i]!=f[b][i]){ a=f[a][i]; b=f[b][i]; } } return f[a][0]; } int cal(int a,int b){ return depth[a]+depth[b]-2*depth[lca(a,b)]; } int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; memset(h,-1,sizeof h); for(i=1;i<n;i++){ int a,b; cin>>a>>b; add(a,b); add(b,a); } dfs(1,0); int k; cin>>k; for(i=1;i<=k;i++){ int x; cin>>x; int now; for(int j=1;j<=x;j++){ int y; cin>>y; num[i].push_back(dfn[y]); if(j==1){ now=y; } else{ now=lca(now,y); } } p[i]=now; sort(num[i].begin(),num[i].end()); } int q; cin>>q; while(q--){ int v,c; cin>>v>>c; int now; for(i=1;i<=c;i++){ cin>>sz[i]; if(i==1){ now=p[sz[i]]; } else{ now=lca(now,p[sz[i]]); } } if(lca(now,v)!=now){ cout<<-2*depth[lca(now,v)]+depth[v]+depth[now]<<endl; continue; } int ans=0x3f3f3f3f; for(i=1;i<=c;i++){ int pos=lower_bound(num[sz[i]].begin(),num[sz[i]].end(),dfn[v])-num[sz[i]].begin(); if(pos!=(int)num[sz[i]].size()){ int tmp=lca(v,id[num[sz[i]][pos]]); ans=min(ans,cal(tmp,v)); } pos=lower_bound(num[sz[i]].begin(),num[sz[i]].end(),dfn[v])-num[sz[i]].begin()-1; if(pos!=-1){ int tmp=lca(v,id[num[sz[i]][pos]]); ans=min(ans,cal(tmp,v)); } } cout<<ans<<endl; } }
没有人不辛苦,只有人不喊疼