依然是没什么难度的模板题..不过查询的时候,没给上限.数组开小就就RE了= =,还有就是根节点要自己找一下..
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=1000;
int n,m,p;
struct EDGE
{
int v,next;
}edge[maxn<<1],q[1200000];
int g[maxn],gg[maxn];
int en,eq;
int ideg[maxn];
int cnt[maxn];
bool vis[maxn];
int fa[maxn];
int find(int x)
{
if (x!=fa[x]) return fa[x]=find(fa[x]);
return x;
}
void tarjan(int u)
{
vis[u]=1;
fa[u]=u;
for (int j=gg[u]; j!=-1; j=q[j].next)
{
int v=q[j].v;
if (vis[v]) cnt[find(v)]++;
}
for (int j=g[u]; j!=-1; j=edge[j].next)
{
int v=edge[j].v;
if (!vis[v])
{
tarjan(v);
fa[v]=u;
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
while(~scanf("%d",&n))
{
memset(cnt,0,sizeof cnt);
int x,y,z;
en=0;
eq=0;
int root=-1;
int num;
memset(g,-1,sizeof g);
memset(gg,-1,sizeof gg);
memset(vis,false,sizeof vis);
memset(ideg,0,sizeof ideg);
for (int i=1; i<=n; i++)
{
scanf("%d:(%d)",&x,&num);
if (root==-1) root=x;
for (int j=1; j<=num; j++)
{
scanf(" %d",&y);
ideg[y]++;
edge[en].v=y;
edge[en].next=g[x];
g[x]=en;
en++;
edge[en].v=x;
edge[en].next=g[y];
g[y]=en;
en++;
}
}
scanf("%d",&m);
char c;
for (int i=1; i<=m; i++)
{
while(scanf("%c",&c))
{
if (c=='(') break;
}
scanf("%d%d",&x,&y);
scanf("%c",&c);
q[eq].v=y;
q[eq].next=gg[x];
gg[x]=eq;
eq++;
q[eq].v=x;
q[eq].next=gg[y];
gg[y]=eq;
eq++;
}
for (int i=1; i<=n; i++)
if (ideg[i]==0)
{
root=i;
break;
}
tarjan(root);
for (int i=1; i<=n; i++)
if (cnt[i]!=0) printf("%d:%d\n",i,cnt[i]);
}
return 0;
}