由于这个题很蛋疼 会有很详细的注释
#pragma comment (linker, "/STACK:1024000000, 1024000000")
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
const int MAX = 1000010;
int n,m;
bool root[N];
int query[N][N];
int tot, head[N];
int father[N],ans[MAX],vis[N],cnt[N];
struct edge{
int v, next;
}node[MAX];
void init(){
tot = 0;
memset(cnt, 0, sizeof(cnt));
memset(vis, -1, sizeof(vis));
memset(root, true, sizeof(root));
memset(head, -1, sizeof(head));
memset(query, 0, sizeof(query));//就是因为这个没有初始化 output exceeded= =。郁闷死!
}
void addedge(int u, int v){//链式前向星
node[tot].v = v;
node[tot].next = head[u];
head[u] = tot++;
}
int find(int x){
if(x != father[x])
father[x] = find(father[x]);
return father[x];
}
void lca(int u, int fa){
father[u] = u;
for(int i=head[u]; i!=-1; i=node[i].next){
int v = node[i].v;
if(vis[v] != -1) continue;
lca(v, fa);
father[v] = u;
}
vis[u] = fa;//由于是单向边 放在中间不会导致死循化,重复统计lca访问次数
for(int i=1; i<=n; i++)
if(vis[i] == fa && query[u][i])
cnt[find(i)] += query[u][i];
}
int main(){
// freopen("in.txt", "r", stdin);
while(scanf("%d",&n) == 1){
init();
for(int i=0; i<n; i++){
int u, num;
scanf("%d:(%d)", &u,&num);
for(int i=0; i<num; i++){
int v;
scanf("%d",&v);
root[v] = false;
addedge(u, v);//有向边
}
}
scanf("%d",&m);
for(int i=0; i<m; i++){
int u, v;
scanf(" (%d %d) ",&u,&v);
query[u][v]++;//用矩阵存储是因为存在重复的询问且统计的是lca的访问次数
query[v][u]++;
ans[i] = -1;
}
int i;
for(i=1; i<=n; i++)
if(root[i]) break;
lca(i, i);//如果求解的是lca本身 必须从根开始搜索 但是如果是求距离就不需要
for(int i=1; i<=n; i++)
if(cnt[i]) printf("%d:%d\n",i,cnt[i]);
}
return 0;
}