专业跟队形
唯一一个有$L^{A_{T^{E_X}}}$的
裸的$LCA$,我用的是$Tarjan~LCA$,注意两点相同特判
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=1010; struct edge{ int next,to; }e[maxn],q[maxn<<1]; int n,m,s,head[maxn],cnt,ans[maxn],heads[maxn],f[maxn],cntc; bool vis[maxn]; int find(int x) { return x==f[x]?x:f[x]=find(f[x]); } void add(int x,int y) { e[++cnt].next=head[x]; e[cnt].to=y; head[x]=cnt; } void adds(int x,int y) { q[++cnt].next=heads[x]; q[cnt].to=y; heads[x]=cnt; } void tarjan(int x,int pre) { for(int v,i=head[x];i;i=e[i].next) { if((v=e[i].to)==pre) continue; tarjan(v=e[i].to,x); int f1=find(x),f2=find(v); if(f1!=f2) f[f2]=f1; } for(int i=heads[x];i;i=q[i].next) if(vis[q[i].to]) ans[(i+1)>>1]=find(q[i].to); vis[x]=1; } int main() { scanf("%d",&s); while(s--) { scanf("%d",&n); cnt=0; memset(head,0,sizeof(head)); memset(heads,0,sizeof(heads)); memset(vis,0,sizeof(vis)); for(int x,num,i=1;i<=n;i++) { scanf("%d",&num); for(int j=1;j<=num;j++) { scanf("%d",&x); add(i,x); } } scanf("%d",&m); cnt=0; for(int x,y,i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(x==y) ans[i]=x; adds(x,y),adds(y,x); } for(int i=1;i<=n;i++) f[i]=i; tarjan(1,0); printf("Case %d:\n",++cntc); for(int i=1;i<=m;i++) printf("%d\n",ans[i]); } return 0; }