基本的LCA的离线版本,如果不懂请移步LCA
AC Code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MXN = 1e3 + 7;
const int MXM = 3e5 + 7;
struct Edge{
int v,nxt;
}E[MXN<<1];
int e,head[MXN],q;
int ans[MXM],pre[MXN],cnt[MXN];
int ancestor[MXN];
bool flag[MXN],vis[MXN];
int findS(int x)
{
return (-1 == pre[x]) ? x : (pre[x] = findS(pre[x]));
}
void join(int x,int y)
{
int fx = findS(x);
int fy = findS(y);
if(fx!=fy) pre[fx] =fy;
}
void add(int u,int v)
{
E[e].v = v;
E[e].nxt = head[u];
head[u] = e++;
E[e].v = u;
E[e].nxt = head[v];
head[v] = e++;
}
struct Query{
int q,nxt,id;
}query[MXM*2];
int h[MXM<<1];
void addQ(int u,int v,int id)
{
query[q].q = v;
query[q].nxt = h[u];
query[q].id = id;
h[u] = q++;
query[q].q = u;
query[q].nxt = h[v];
query[q].id = id;
h[v] = q++;
}
void init()
{
e = 0;q = 0;
memset(h,-1,sizeof h);
memset(flag,0,sizeof flag);
memset(vis,0,sizeof vis);
memset(ancestor,0,sizeof ancestor);
memset(ans,0,sizeof ans);
memset(pre,-1,sizeof pre);
memset(cnt,0,sizeof cnt);
memset(head,-1,sizeof head);
}
void LCA(int u)
{
ancestor[u] = u;
vis[u] = true;
for(int i=head[u];~i;i=E[i].nxt) {
int v = E[i].v;
if(vis[v]) continue;
// cout<<u<<endl;
LCA(v);
join(u,v);
ancestor[findS(u)] = u;
}
for(int i=h[u];~i;i=query[i].nxt){
int v = query[i].q;
if(vis[v]) {
//cout<<v<<"---"<<findS(v)<<endl;
ans[query[i].id] = ancestor[findS(v)];
//cout<<v<<"----"<<ancestor[findS(v)]<<endl;
}
}
}
int main()
{
int n;//freopen("in.txt","r",stdin);
while(cin>>n)
{
init();
int u,v,j,Q,k;
for(int i=1;i<=n;i++) {
scanf("%d:(%d)",&u,&k);
while(k--) {
scanf("%d",&v);
add(u,v); flag[v] = true;
}
}
scanf("%d",&Q);
for(int i=0;i<Q;i++) {
char ch;cin>>ch;
scanf("%d %d)",&u,&v);
addQ(u,v,i);
}
int rt;
for(int i=1;i<=n;i++) {
if(!flag[i]) {rt=i;break;}
}
LCA(rt);
for(int i=0;i<Q;i++) cnt[ans[i]] ++;
for(int i=1;i<=n;i++) {
if(!cnt[i]) continue;
printf("%d:%d\n",i,cnt[i]);
}
}
return 0;
}