NC13950. Alliances
描述
输入描述
输入的第一行包含一个整数n,代表树国中的城市数。
接下来n−1行,每行包含两个整数u和v,代表城市u和v之间存在一条道路。
接下来一行包含一个整数k,代表树国中的帮派数。
接下来k行,每行描述一个帮派。第i行的第一个整数c[i]代表第i个帮派占据的城市数,接下来c[i]个整数,代表被第i个帮派占据的城市。
接下来一行包含一个整数Q,代表询问数。
接下来Q行,每行描述一个询问。每行的前两个整数V和t[i]代表本次询问中的首都与需要考虑的帮派集合的大小。接下来t[i]个整数代表本次询问中需要考虑的帮派。.
输出描述
对于每个询问,输出一行,包含一个整数,代表询问的答案。
示例1
输入:
7 1 2 1 3 2 4 2 5 3 6 3 7 2 2 6 7 1 4 3 5 1 2 1 1 1 5 2 1 2
输出:
2 1 1
C++(g++ 7.5.0) 解法, 执行用时: 2552ms, 内存消耗: 110108K, 提交时间: 2023-04-19 19:23:51
#include <bits/stdc++.h> using namespace std; const int N=5e5+50,M=20; vector<int>g[N],q[N]; vector<int>x; int f[N][M],dep[N],dfn[N],id,top[N]; void dfs(int u,int fa) { dfn[u]=++id;dep[u]+=dep[fa]+1; f[u][0]=fa;for(int i=1;i<20;i++) f[u][i]=f[f[u][i-1]][i-1]; for(int v:g[u]) if(v!=fa) dfs(v,u); } int lca(int u,int v) { if(dep[v]>dep[u]) swap(u,v);//假定u是dep大的. for(int i=19;i>=0;i--) { if(dep[f[u][i]]>=dep[v]) u=f[u][i]; }if(u==v) return v; for(int i=19;i>=0;i--) { if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i]; }return f[u][0]; } int dis(int u,int v) {return dep[u]+dep[v]-2*dep[lca(u,v)];} bool cmp(int a,int b) {return dfn[a]<dfn[b];} int main() { int n;scanf("%d",&n); for(int i=1;i<n;i++) { int u,v;scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); }dfs(1,1);int t;scanf("%d",&t); for(int i=1;i<=t;i++) { int u,v;scanf("%d",&u); for(int j=0;j<u;j++) { scanf("%d",&v);q[i].push_back(v); if(j==0) top[i]=v; else top[i]=lca(top[i],v); }sort(q[i].begin(),q[i].end(),cmp); }int Q;scanf("%d",&Q); while(Q--) { x.clear();int V,LCA;scanf("%d",&V);int u,v;scanf("%d",&u); for(int i=0;i<u;i++) { scanf("%d",&v);x.push_back(v); if(i==0) LCA=top[v]; else LCA=lca(LCA,top[v]); }if(LCA!=lca(LCA,V)) printf("%d\n",dis(V,LCA)); else { int ans=2e9; for(int e:x) { int sz=q[e].size();int pos=sz,r=sz-1,l=0; while(l<=r) { int mid=(l+r)>>1; if(dfn[q[e][mid]]>=dfn[V]) pos=mid,r=mid-1; else l=mid+1; } if(pos!=0) ans=min(ans,dis(V,lca(q[e][pos-1],V))); if(pos!=sz) ans=min(ans,dis(V,lca(q[e][pos],V))); }printf("%d\n",ans); } } return 0; }
C++11(clang++ 3.9) 解法, 执行用时: 1963ms, 内存消耗: 99960K, 提交时间: 2020-08-14 00:51:03
#include<bits/stdc++.h> using namespace std; vector<int>R[500005],T[500005]; vector<int>::iterator it; int a[500005],Dep[500005]={0},F[500005][20],dfn[500005],top[500005],ID[500005],t,tot=0; void DFS(int x,int fa) { int i,j,k; dfn[x]=++tot,ID[tot]=x; for(i=0;i<R[x].size();i++) { j=R[x][i]; if(j==fa)continue; Dep[j]=Dep[x]+1,F[j][0]=x; for(k=1;k<=t;k++)F[j][k]=F[F[j][k-1]][k-1]; DFS(j,x); } } int lca(int x,int y) { int i; if(Dep[x]>Dep[y])swap(x,y); for(i=t;i>=0;i--)if(Dep[F[y][i]]>=Dep[x])y=F[y][i]; if(y==x)return x; for(i=t;i>=0;i--)if(F[y][i]!=F[x][i])y=F[y][i],x=F[x][i]; return F[x][0]; } int main() { int i,j,k,x,s,Top,ans,n,m,q; scanf("%d",&n),t=(int)(log(n)/log(2))+1; for(i=1;i<n;i++) { scanf("%d%d",&j,&k); R[j].push_back(k),R[k].push_back(j); } F[1][0]=1,DFS(1,0); scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d",&s); for(j=1;j<=s;j++) { scanf("%d",&x); T[i].push_back(dfn[x]); if(j==1)top[i]=x; else top[i]=lca(top[i],x); } sort(T[i].begin(),T[i].end()); } scanf("%d",&q); while(q--) { scanf("%d%d",&x,&s),ans=1e9; for(i=1;i<=s;i++) { scanf("%d",&a[i]); if(i==1)Top=top[a[i]]; else Top=lca(Top,top[a[i]]); } if(lca(Top,x)!=Top){printf("%d\n",Dep[Top]+Dep[x]-2*Dep[lca(Top,x)]);continue;} for(i=1;i<=s;i++) { it=lower_bound(T[a[i]].begin(),T[a[i]].end(),dfn[x]); if(it!=T[a[i]].end())j=lca(x,ID[*it]),ans=min(ans,Dep[x]-Dep[j]); if(it!=T[a[i]].begin())j=lca(x,ID[*(--it)]),ans=min(ans,Dep[x]-Dep[j]); } printf("%d\n",ans); } return 0; }