#include<iostream>
#include<vector>
using namespace std;
int T[905][905];//存储树
int n[905];//存储结果
bool color[905];//标记
int ancestor[905];//祖先
int p[905];//并查集使用
int r[905];//并查集使用
bool b[905];//用于查询根节点
vector<int> q[905];//存储查询
int N,NQ;//节点树和查询数
void MakeSet(int n)
{
int i;
for(i=1;i<=n;++i)
{
p[i]=i;
r[i]=0;
}
}
int FindSet(int x)
{
if(x!=p[x])
{
p[x]=FindSet(p[x]);
}
return p[x];
}
void Link(int x,int y)
{
if(r[x]>r[y])
p[y]=x;
else
p[x]=y;
if(r[x]==r[y])
r[y]=r[y]+1;
}
void Union(int x,int y)
{
int m=FindSet(x);
int n=FindSet(y);
if(m!=n)
Link(m,n);
}
void LCA(int u)
{
ancestor[FindSet(u)]=u;
//ancestor[u]=u;
int i=0;
while(T[u][i]!=-1)
{
LCA(T[u][i]);
Union(u,T[u][i]);
ancestor[FindSet(u)]=u;
i++;
}
color[u]=true;
i=0;
int size=q[u].size();
for(i=0;i<size;++i)
{
int v=q[u][i];
if(color[ v ]==true)
{
n[ancestor[FindSet(v)]]++;
}
}
}
int main()
{
int i,j,t;
int prt,cld;
char ch;
char cl,cr;
int u,v;
while(scanf("%d",&N)!=EOF)
{
memset(T,-1,sizeof(T));
memset(color,0,sizeof(color));
memset(n,0,sizeof(n));
memset(b,0,sizeof(b));
for(i=0;i<904;++i)
q[i].clear();
for(i=0;i<N;++i)
{
scanf("%d%c%c%d%c",&prt,&ch,&cl,&t,&cr);
for(j=0;j<t;++j)
{
scanf("%d",&cld);
T[prt][j]=cld;
b[cld]=true;
}
}
scanf("%d",&NQ);
for(i=0;i<NQ;++i)
{
while(scanf("%c",&cl))
if(cl=='(')
break;
scanf("%d%d",&u,&v);
q[u].push_back(v);
q[v].push_back(u);
while(scanf("%c",&cl))
if(cl==')')
break;
}
//查找根节点
for(i=1;i<=N;++i)
{
if(b[i]==false)
break;
}
MakeSet(N);
LCA(i);
for(i=1;i<=N;++i)
{
if(n[i]!=0)
printf("%d:%d\n",i,n[i]);
}
}
return 0;
}
|